зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1715892 - Unify locale/DateTimeFormat to mozilla::intl::AppDateTimeFormat; r=platform-i18n-reviewers,dminor
I considered removing this class initially, but it's actually a pretty useful abstraction over the DateTimeFormat interface when used specifically with Gecko. It applies the OS preferences and provides some caching behavior. Differential Revision: https://phabricator.services.mozilla.com/D131671
This commit is contained in:
Родитель
8589e5b393
Коммит
9b5497020e
|
@ -4,32 +4,30 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "mozilla/intl/DateTimePatternGenerator.h"
|
||||
#include "mozilla/intl/FormatBuffer.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "OSPreferences.h"
|
||||
#include "mozIOSPreferences.h"
|
||||
#include "unicode/dtfmtsym.h"
|
||||
#include "unicode/udatpg.h"
|
||||
|
||||
namespace mozilla {
|
||||
using namespace mozilla::intl;
|
||||
namespace mozilla::intl {
|
||||
|
||||
nsCString* DateTimeFormat::mLocale = nullptr;
|
||||
nsTHashMap<nsCStringHashKey, UDateFormat*>* DateTimeFormat::mFormatCache;
|
||||
nsCString* AppDateTimeFormat::mLocale = nullptr;
|
||||
nsTHashMap<nsCStringHashKey, DateTimeFormat*>* AppDateTimeFormat::mFormatCache;
|
||||
|
||||
static const int32_t DATETIME_FORMAT_INITIAL_LEN = 127;
|
||||
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::Initialize() {
|
||||
nsresult AppDateTimeFormat::Initialize() {
|
||||
if (mLocale) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mLocale = new nsCString();
|
||||
AutoTArray<nsCString, 10> regionalPrefsLocales;
|
||||
intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(
|
||||
regionalPrefsLocales);
|
||||
LocaleService::GetInstance()->GetRegionalPrefsLocales(regionalPrefsLocales);
|
||||
mLocale->Assign(regionalPrefsLocales[0]);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -37,32 +35,31 @@ nsresult DateTimeFormat::Initialize() {
|
|||
|
||||
// performs a locale sensitive date formatting operation on the PRTime parameter
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::FormatPRTime(
|
||||
const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector, const PRTime aPrTime,
|
||||
nsAString& aStringOut) {
|
||||
return FormatUDateTime(aDateFormatSelector, aTimeFormatSelector,
|
||||
(aPrTime / PR_USEC_PER_MSEC), nullptr, aStringOut);
|
||||
nsresult AppDateTimeFormat::Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const PRTime aPrTime,
|
||||
nsAString& aStringOut) {
|
||||
return AppDateTimeFormat::Format(
|
||||
aStyle, (static_cast<double>(aPrTime) / PR_USEC_PER_MSEC), nullptr,
|
||||
aStringOut);
|
||||
}
|
||||
|
||||
// performs a locale sensitive date formatting operation on the PRExplodedTime
|
||||
// parameter
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::FormatPRExplodedTime(
|
||||
const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector,
|
||||
const PRExplodedTime* aExplodedTime, nsAString& aStringOut) {
|
||||
return FormatUDateTime(aDateFormatSelector, aTimeFormatSelector,
|
||||
(PR_ImplodeTime(aExplodedTime) / PR_USEC_PER_MSEC),
|
||||
&(aExplodedTime->tm_params), aStringOut);
|
||||
nsresult AppDateTimeFormat::Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut) {
|
||||
return AppDateTimeFormat::Format(
|
||||
aStyle, (PR_ImplodeTime(aExplodedTime) / PR_USEC_PER_MSEC),
|
||||
&(aExplodedTime->tm_params), aStringOut);
|
||||
}
|
||||
|
||||
// performs a locale sensitive date formatting operation on the PRExplodedTime
|
||||
// parameter, using the specified options.
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::FormatDateTime(
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
const DateTimeFormat::Skeleton aSkeleton, nsAString& aStringOut) {
|
||||
nsresult AppDateTimeFormat::Format(const DateTimeFormat::ComponentsBag& aBag,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut) {
|
||||
// set up locale data
|
||||
nsresult rv = Initialize();
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -71,158 +68,59 @@ nsresult DateTimeFormat::FormatDateTime(
|
|||
|
||||
aStringOut.Truncate();
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
nsAutoCString skeleton;
|
||||
switch (aSkeleton) {
|
||||
case Skeleton::yyyyMM:
|
||||
skeleton.AssignASCII("yyyyMM");
|
||||
break;
|
||||
case Skeleton::yyyyMMMM:
|
||||
skeleton.AssignASCII("yyyyMMMM");
|
||||
break;
|
||||
case Skeleton::E:
|
||||
skeleton.AssignASCII("E");
|
||||
break;
|
||||
case Skeleton::EEEE:
|
||||
skeleton.AssignASCII("EEEE");
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled skeleton enum");
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
if (!OSPreferences::GetPatternForSkeleton(skeleton, *mLocale, str)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoString pattern = NS_ConvertUTF8toUTF16(str);
|
||||
|
||||
nsAutoString timeZoneID;
|
||||
BuildTimeZoneString(aExplodedTime->tm_params, timeZoneID);
|
||||
|
||||
UDateFormat* dateTimeFormat =
|
||||
udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(),
|
||||
reinterpret_cast<const UChar*>(timeZoneID.BeginReading()),
|
||||
timeZoneID.Length(),
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()),
|
||||
pattern.Length(), &status);
|
||||
auto genResult = DateTimePatternGenerator::TryCreate(mLocale->get());
|
||||
NS_ENSURE_TRUE(genResult.isOk(), NS_ERROR_FAILURE);
|
||||
auto dateTimePatternGenerator = genResult.unwrap();
|
||||
|
||||
if (U_SUCCESS(status) && dateTimeFormat) {
|
||||
UDate udate =
|
||||
static_cast<float>((PR_ImplodeTime(aExplodedTime) / PR_USEC_PER_MSEC));
|
||||
auto result = DateTimeFormat::TryCreateFromComponents(
|
||||
*mLocale, aBag, dateTimePatternGenerator.get(), Some(timeZoneID));
|
||||
NS_ENSURE_TRUE(result.isOk(), NS_ERROR_FAILURE);
|
||||
auto dateTimeFormat = result.unwrap().release();
|
||||
|
||||
aStringOut.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
int32_t dateTimeLen =
|
||||
udat_format(dateTimeFormat, udate,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
DATETIME_FORMAT_INITIAL_LEN, nullptr, &status);
|
||||
aStringOut.SetLength(dateTimeLen);
|
||||
double unixEpoch =
|
||||
static_cast<float>((PR_ImplodeTime(aExplodedTime) / PR_USEC_PER_MSEC));
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udat_format(dateTimeFormat, udate,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
dateTimeLen, nullptr, &status);
|
||||
}
|
||||
}
|
||||
|
||||
udat_close(dateTimeFormat);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
aStringOut.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
nsTStringToBufferAdapter buffer(aStringOut);
|
||||
NS_ENSURE_TRUE(dateTimeFormat->TryFormat(unixEpoch, buffer).isOk(),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::GetCalendarSymbol(const Field aField,
|
||||
const Style aStyle,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut) {
|
||||
nsresult rv = Initialize();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
icu::DateFormatSymbols::DtWidthType widthType;
|
||||
switch (aStyle) {
|
||||
case Style::Wide:
|
||||
widthType = icu::DateFormatSymbols::DtWidthType::WIDE;
|
||||
break;
|
||||
case Style::Abbreviated:
|
||||
widthType = icu::DateFormatSymbols::DtWidthType::ABBREVIATED;
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t count;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::Locale locale = icu::Locale::createCanonical(mLocale->get());
|
||||
|
||||
UDate udate =
|
||||
static_cast<float>((PR_ImplodeTime(aExplodedTime) / PR_USEC_PER_MSEC));
|
||||
|
||||
nsAutoString timeZoneID;
|
||||
BuildTimeZoneString(aExplodedTime->tm_params, timeZoneID);
|
||||
std::unique_ptr<icu::TimeZone> timeZone(
|
||||
icu::TimeZone::createTimeZone(timeZoneID.BeginReading()));
|
||||
std::unique_ptr<icu::Calendar> cal(
|
||||
icu::Calendar::createInstance(timeZone.release(), locale, status));
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
cal->setTime(udate, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
std::unique_ptr<icu::DateFormatSymbols> dfs(
|
||||
icu::DateFormatSymbols::createForLocale(locale, status));
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (aField == Field::Month) {
|
||||
int32_t month = cal->get(UCAL_MONTH, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
/**
|
||||
* An internal utility function to serialize a Maybe<DateTimeFormat::Style> to
|
||||
* an int, to be used as a caching key.
|
||||
*/
|
||||
static int StyleToInt(const Maybe<DateTimeFormat::Style>& aStyle) {
|
||||
if (aStyle.isSome()) {
|
||||
switch (*aStyle) {
|
||||
case DateTimeFormat::Style::Full:
|
||||
return 1;
|
||||
case DateTimeFormat::Style::Long:
|
||||
return 2;
|
||||
case DateTimeFormat::Style::Medium:
|
||||
return 3;
|
||||
case DateTimeFormat::Style::Short:
|
||||
return 4;
|
||||
}
|
||||
const auto* months = dfs->getMonths(
|
||||
count, icu::DateFormatSymbols::DtContextType::STANDALONE, widthType);
|
||||
if (month < 0 || month >= count) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
aStringOut.Assign(months[month].getBuffer(), months[month].length());
|
||||
} else if (aField == Field::Weekday) {
|
||||
int32_t weekday = cal->get(UCAL_DAY_OF_WEEK, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
const auto* weekdays = dfs->getWeekdays(
|
||||
count, icu::DateFormatSymbols::DtContextType::STANDALONE, widthType);
|
||||
if (weekday < 0 || weekday >= count) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
aStringOut.Assign(weekdays[weekday].getBuffer(),
|
||||
weekdays[weekday].length());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// performs a locale sensitive date formatting operation on the UDate parameter
|
||||
/*static*/
|
||||
nsresult DateTimeFormat::FormatUDateTime(
|
||||
const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector, const UDate aUDateTime,
|
||||
const PRTimeParameters* aTimeParameters, nsAString& aStringOut) {
|
||||
int32_t dateTimeLen = 0;
|
||||
nsresult AppDateTimeFormat::Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const double aUnixEpoch,
|
||||
const PRTimeParameters* aTimeParameters,
|
||||
nsAString& aStringOut) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// return, nothing to format
|
||||
if (aDateFormatSelector == kDateFormatNone &&
|
||||
aTimeFormatSelector == kTimeFormatNone) {
|
||||
if (aStyle.date.isNothing() && aStyle.time.isNothing()) {
|
||||
aStringOut.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -234,12 +132,10 @@ nsresult DateTimeFormat::FormatUDateTime(
|
|||
return rv;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
nsAutoCString key;
|
||||
key.AppendInt((int)aDateFormatSelector);
|
||||
key.AppendInt(StyleToInt(aStyle.date));
|
||||
key.Append(':');
|
||||
key.AppendInt((int)aTimeFormatSelector);
|
||||
key.AppendInt(StyleToInt(aStyle.time));
|
||||
if (aTimeParameters) {
|
||||
key.Append(':');
|
||||
key.AppendInt(aTimeParameters->tp_gmt_offset);
|
||||
|
@ -249,49 +145,44 @@ nsresult DateTimeFormat::FormatUDateTime(
|
|||
|
||||
if (mFormatCache && mFormatCache->Count() == kMaxCachedFormats) {
|
||||
// Don't allow a pathological page to extend the cache unreasonably.
|
||||
NS_WARNING("flushing UDateFormat cache");
|
||||
NS_WARNING("flushing DateTimeFormat cache");
|
||||
DeleteCache();
|
||||
}
|
||||
if (!mFormatCache) {
|
||||
mFormatCache =
|
||||
new nsTHashMap<nsCStringHashKey, UDateFormat*>(kMaxCachedFormats);
|
||||
new nsTHashMap<nsCStringHashKey, DateTimeFormat*>(kMaxCachedFormats);
|
||||
}
|
||||
|
||||
UDateFormat*& dateTimeFormat = mFormatCache->LookupOrInsert(key);
|
||||
DateTimeFormat*& dateTimeFormat = mFormatCache->LookupOrInsert(key);
|
||||
|
||||
if (!dateTimeFormat) {
|
||||
// We didn't have a cached formatter for this key, so create one.
|
||||
|
||||
int32_t dateFormatStyle;
|
||||
switch (aDateFormatSelector) {
|
||||
case kDateFormatLong:
|
||||
dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleLong;
|
||||
break;
|
||||
case kDateFormatShort:
|
||||
dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleShort;
|
||||
break;
|
||||
case kDateFormatNone:
|
||||
dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleNone;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsDateFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
int32_t dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleNone;
|
||||
if (aStyle.date.isSome()) {
|
||||
switch (*aStyle.date) {
|
||||
case DateTimeFormat::Style::Full:
|
||||
case DateTimeFormat::Style::Long:
|
||||
dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleLong;
|
||||
break;
|
||||
case DateTimeFormat::Style::Medium:
|
||||
case DateTimeFormat::Style::Short:
|
||||
dateFormatStyle = mozIOSPreferences::dateTimeFormatStyleShort;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t timeFormatStyle;
|
||||
switch (aTimeFormatSelector) {
|
||||
case kTimeFormatLong:
|
||||
timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleLong;
|
||||
break;
|
||||
case kTimeFormatShort:
|
||||
timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleShort;
|
||||
break;
|
||||
case kTimeFormatNone:
|
||||
timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleNone;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown nsDateFormatSelector");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
int32_t timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleNone;
|
||||
if (aStyle.time.isSome()) {
|
||||
switch (*aStyle.time) {
|
||||
case DateTimeFormat::Style::Full:
|
||||
case DateTimeFormat::Style::Long:
|
||||
timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleLong;
|
||||
break;
|
||||
case DateTimeFormat::Style::Medium:
|
||||
case DateTimeFormat::Style::Short:
|
||||
timeFormatStyle = mozIOSPreferences::dateTimeFormatStyleShort;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
|
@ -301,49 +192,32 @@ nsresult DateTimeFormat::FormatUDateTime(
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoString pattern = NS_ConvertUTF8toUTF16(str);
|
||||
|
||||
Maybe<Span<const char16_t>> timeZoneOverride = Nothing();
|
||||
nsAutoString timeZoneID;
|
||||
if (aTimeParameters) {
|
||||
nsAutoString timeZoneID;
|
||||
BuildTimeZoneString(*aTimeParameters, timeZoneID);
|
||||
|
||||
dateTimeFormat =
|
||||
udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(),
|
||||
reinterpret_cast<const UChar*>(timeZoneID.BeginReading()),
|
||||
timeZoneID.Length(),
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()),
|
||||
pattern.Length(), &status);
|
||||
} else {
|
||||
dateTimeFormat =
|
||||
udat_open(UDAT_PATTERN, UDAT_PATTERN, mLocale->get(), nullptr, -1,
|
||||
reinterpret_cast<const UChar*>(pattern.BeginReading()),
|
||||
pattern.Length(), &status);
|
||||
timeZoneOverride =
|
||||
Some(Span<const char16_t>(timeZoneID.Data(), timeZoneID.Length()));
|
||||
}
|
||||
|
||||
auto result = DateTimeFormat::TryCreateFromPattern(*mLocale, pattern,
|
||||
timeZoneOverride);
|
||||
NS_ENSURE_TRUE(result.isOk(), NS_ERROR_FAILURE);
|
||||
dateTimeFormat = result.unwrap().release();
|
||||
}
|
||||
|
||||
if (U_SUCCESS(status) && dateTimeFormat) {
|
||||
aStringOut.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
dateTimeLen =
|
||||
udat_format(dateTimeFormat, aUDateTime,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
DATETIME_FORMAT_INITIAL_LEN, nullptr, &status);
|
||||
aStringOut.SetLength(dateTimeLen);
|
||||
MOZ_ASSERT(dateTimeFormat);
|
||||
|
||||
if (status == U_BUFFER_OVERFLOW_ERROR) {
|
||||
status = U_ZERO_ERROR;
|
||||
udat_format(dateTimeFormat, aUDateTime,
|
||||
reinterpret_cast<UChar*>(aStringOut.BeginWriting()),
|
||||
dateTimeLen, nullptr, &status);
|
||||
}
|
||||
}
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
aStringOut.SetLength(DATETIME_FORMAT_INITIAL_LEN);
|
||||
nsTStringToBufferAdapter buffer(aStringOut);
|
||||
NS_ENSURE_TRUE(dateTimeFormat->TryFormat(aUnixEpoch, buffer).isOk(),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void DateTimeFormat::BuildTimeZoneString(
|
||||
void AppDateTimeFormat::BuildTimeZoneString(
|
||||
const PRTimeParameters& aTimeParameters, nsAString& aStringOut) {
|
||||
aStringOut.Truncate();
|
||||
aStringOut.Append(u"GMT");
|
||||
|
@ -358,10 +232,10 @@ void DateTimeFormat::BuildTimeZoneString(
|
|||
}
|
||||
|
||||
/*static*/
|
||||
void DateTimeFormat::DeleteCache() {
|
||||
void AppDateTimeFormat::DeleteCache() {
|
||||
if (mFormatCache) {
|
||||
for (const auto& entry : mFormatCache->Values()) {
|
||||
udat_close(entry);
|
||||
for (const auto& dateTimeFormat : mFormatCache->Values()) {
|
||||
delete dateTimeFormat;
|
||||
}
|
||||
delete mFormatCache;
|
||||
mFormatCache = nullptr;
|
||||
|
@ -369,11 +243,9 @@ void DateTimeFormat::DeleteCache() {
|
|||
}
|
||||
|
||||
/*static*/
|
||||
void DateTimeFormat::Shutdown() {
|
||||
void AppDateTimeFormat::Shutdown() {
|
||||
DeleteCache();
|
||||
if (mLocale) {
|
||||
delete mLocale;
|
||||
}
|
||||
delete mLocale;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::intl
|
||||
|
|
|
@ -4,95 +4,78 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_DateTimeFormat_h
|
||||
#define mozilla_DateTimeFormat_h
|
||||
#ifndef mozilla_intl_AppDateTimeFormat_h
|
||||
#define mozilla_intl_AppDateTimeFormat_h
|
||||
|
||||
#include <time.h>
|
||||
#include "gtest/MozGtestFriend.h"
|
||||
#include "nsTHashMap.h"
|
||||
#include "nsString.h"
|
||||
#include "prtime.h"
|
||||
#include "unicode/udat.h"
|
||||
#include "mozilla/intl/DateTimeFormat.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace mozilla::intl {
|
||||
|
||||
enum nsDateFormatSelector : long {
|
||||
// Do not change the order of the values below (see bug 1225696).
|
||||
kDateFormatNone = 0, // do not include the date in the format string
|
||||
kDateFormatLong, // provides the long date format for the given locale
|
||||
kDateFormatShort, // provides the short date format for the given locale
|
||||
};
|
||||
|
||||
enum nsTimeFormatSelector : long {
|
||||
kTimeFormatNone = 0, // don't include the time in the format string
|
||||
kTimeFormatLong, // provides the time format with seconds in the given
|
||||
// locale
|
||||
kTimeFormatShort // provides the time format without seconds in the given
|
||||
// locale
|
||||
};
|
||||
|
||||
class DateTimeFormat {
|
||||
/**
|
||||
* Get a DateTimeFormat for use in Gecko. This specialized DateTimeFormat
|
||||
* respects the user's OS and app preferences, and provides caching of the
|
||||
* underlying mozilla::intl resources.
|
||||
*/
|
||||
class AppDateTimeFormat {
|
||||
public:
|
||||
enum class Field { Month, Weekday };
|
||||
/**
|
||||
* Format a DateTime using the applied app and OS-level preferences, with a
|
||||
* style bag and the PRTime.
|
||||
*/
|
||||
static nsresult Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const PRTime aPrTime, nsAString& aStringOut);
|
||||
|
||||
enum class Style { Wide, Abbreviated };
|
||||
/**
|
||||
* Format a DateTime using the applied app and OS-level preferences, with a
|
||||
* style bag and the PRExplodedTime.
|
||||
*/
|
||||
static nsresult Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut);
|
||||
|
||||
// Weekday (E, EEEE) only used in Thunderbird.
|
||||
enum class Skeleton { yyyyMM, yyyyMMMM, E, EEEE };
|
||||
|
||||
// performs a locale sensitive date formatting operation on the PRTime
|
||||
// parameter
|
||||
static nsresult FormatPRTime(const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector,
|
||||
const PRTime aPrTime, nsAString& aStringOut);
|
||||
|
||||
// performs a locale sensitive date formatting operation on the PRExplodedTime
|
||||
// parameter
|
||||
static nsresult FormatPRExplodedTime(
|
||||
const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector,
|
||||
const PRExplodedTime* aExplodedTime, nsAString& aStringOut);
|
||||
|
||||
// performs a locale sensitive date formatting operation on the PRExplodedTime
|
||||
// parameter, using the specified options.
|
||||
static nsresult FormatDateTime(const PRExplodedTime* aExplodedTime,
|
||||
const Skeleton aSkeleton,
|
||||
nsAString& aStringOut);
|
||||
|
||||
// finds the locale sensitive display name for the specified field on the
|
||||
// PRExplodedTime parameter
|
||||
static nsresult GetCalendarSymbol(const Field aField, const Style aStyle,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut);
|
||||
/**
|
||||
* Format a DateTime using the applied app and OS-level preferences, with a
|
||||
* components bag and the PRExplodedTime.
|
||||
*/
|
||||
static nsresult Format(const DateTimeFormat::ComponentsBag& aComponents,
|
||||
const PRExplodedTime* aExplodedTime,
|
||||
nsAString& aStringOut);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
DateTimeFormat() = delete;
|
||||
AppDateTimeFormat() = delete;
|
||||
|
||||
static nsresult Initialize();
|
||||
static void DeleteCache();
|
||||
static const size_t kMaxCachedFormats = 15;
|
||||
|
||||
FRIEND_TEST(DateTimeFormat, FormatPRExplodedTime);
|
||||
FRIEND_TEST(DateTimeFormat, DateFormatSelectors);
|
||||
FRIEND_TEST(DateTimeFormat, FormatPRExplodedTimeForeign);
|
||||
FRIEND_TEST(DateTimeFormat, DateFormatSelectorsForeign);
|
||||
FRIEND_TEST(AppDateTimeFormat, FormatPRExplodedTime);
|
||||
FRIEND_TEST(AppDateTimeFormat, DateFormatSelectors);
|
||||
FRIEND_TEST(AppDateTimeFormat, FormatPRExplodedTimeForeign);
|
||||
FRIEND_TEST(AppDateTimeFormat, DateFormatSelectorsForeign);
|
||||
|
||||
// performs a locale sensitive date formatting operation on the UDate
|
||||
// parameter
|
||||
static nsresult FormatUDateTime(
|
||||
const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector, const UDate aUDateTime,
|
||||
const PRTimeParameters* aTimeParameters, nsAString& aStringOut);
|
||||
/**
|
||||
* Format a DateTime using the applied app and OS-level preferences, with a
|
||||
* components bag and the PRExplodedTime.
|
||||
*/
|
||||
static nsresult Format(const DateTimeFormat::StyleBag& aStyle,
|
||||
const double aUnixEpoch,
|
||||
const PRTimeParameters* aTimeParameters,
|
||||
nsAString& aStringOut);
|
||||
|
||||
static void BuildTimeZoneString(const PRTimeParameters& aTimeParameters,
|
||||
nsAString& aStringOut);
|
||||
|
||||
static nsCString* mLocale;
|
||||
static nsTHashMap<nsCStringHashKey, UDateFormat*>* mFormatCache;
|
||||
static nsTHashMap<nsCStringHashKey, DateTimeFormat*>* mFormatCache;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::intl
|
||||
|
||||
#endif /* mozilla_DateTimeFormat_h */
|
||||
#endif /* mozilla_intl_AppDateTimeFormat_h */
|
||||
|
|
|
@ -25,12 +25,12 @@ XPIDL_SOURCES += [
|
|||
XPIDL_MODULE = "locale"
|
||||
|
||||
EXPORTS += [
|
||||
"DateTimeFormat.h",
|
||||
"nsLanguageAtomService.h",
|
||||
"nsUConvPropertySearch.h",
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.intl += [
|
||||
"AppDateTimeFormat.h",
|
||||
"LocaleService.h",
|
||||
"MozLocaleBindings.h",
|
||||
"OSPreferences.h",
|
||||
|
@ -38,7 +38,7 @@ EXPORTS.mozilla.intl += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"DateTimeFormat.cpp",
|
||||
"AppDateTimeFormat.cpp",
|
||||
"LocaleService.cpp",
|
||||
"nsLanguageAtomService.cpp",
|
||||
"nsUConvPropertySearch.cpp",
|
||||
|
|
|
@ -1,20 +1,33 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "DateTimeFormat.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "mozilla/intl/DateTimeFormat.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace mozilla::intl {
|
||||
using Style = DateTimeFormat::Style;
|
||||
using StyleBag = DateTimeFormat::StyleBag;
|
||||
using ComponentsBag = DateTimeFormat::ComponentsBag;
|
||||
|
||||
TEST(DateTimeFormat, FormatPRExplodedTime)
|
||||
static DateTimeFormat::StyleBag ToStyleBag(Maybe<DateTimeFormat::Style> date,
|
||||
Maybe<DateTimeFormat::Style> time) {
|
||||
DateTimeFormat::StyleBag style;
|
||||
style.date = date;
|
||||
style.time = time;
|
||||
return style;
|
||||
}
|
||||
|
||||
TEST(AppDateTimeFormat, FormatPRExplodedTime)
|
||||
{
|
||||
PRTime prTime = 0;
|
||||
PRExplodedTime prExplodedTime;
|
||||
PR_ExplodeTime(prTime, PR_GMTParameters, &prExplodedTime);
|
||||
|
||||
mozilla::DateTimeFormat::mLocale = new nsCString("en-US");
|
||||
mozilla::DateTimeFormat::DeleteCache();
|
||||
AppDateTimeFormat::mLocale = new nsCString("en-US");
|
||||
AppDateTimeFormat::DeleteCache();
|
||||
StyleBag style = ToStyleBag(Some(Style::Long), Some(Style::Long));
|
||||
|
||||
nsAutoString formattedTime;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("January") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("1970") != kNotFound);
|
||||
|
@ -22,8 +35,9 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
formattedTime.Find("00:00:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 19, 0, 1, 0, 1970, 4, 0, {(19 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("January") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("1970") != kNotFound);
|
||||
|
@ -32,8 +46,7 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
|
||||
prExplodedTime = {0, 0, 0, 7, 1,
|
||||
0, 1970, 4, 0, {(6 * 60 * 60), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("January") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("1970") != kNotFound);
|
||||
|
@ -43,8 +56,7 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
prExplodedTime = {
|
||||
0, 0, 29, 11, 1,
|
||||
0, 1970, 4, 0, {(10 * 60 * 60) + (29 * 60), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("January") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("1970") != kNotFound);
|
||||
|
@ -52,8 +64,7 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
formattedTime.Find("11:29:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 37, 23, 31, 11, 1969, 3, 364, {-(23 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("December") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("31") != kNotFound);
|
||||
|
@ -62,8 +73,7 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
formattedTime.Find("23:37:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 0, 17, 31, 11, 1969, 3, 364, {-(7 * 60 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("December") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("31") != kNotFound);
|
||||
|
@ -74,8 +84,7 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
prExplodedTime = {
|
||||
0, 0, 47, 14, 31,
|
||||
11, 1969, 3, 364, {-((10 * 60 * 60) + (13 * 60)), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("December") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("31") != kNotFound);
|
||||
|
@ -84,52 +93,70 @@ TEST(DateTimeFormat, FormatPRExplodedTime)
|
|||
formattedTime.Find("14:47:00") != kNotFound);
|
||||
}
|
||||
|
||||
TEST(DateTimeFormat, DateFormatSelectors)
|
||||
TEST(AppDateTimeFormat, DateFormatSelectors)
|
||||
{
|
||||
PRTime prTime = 0;
|
||||
PRExplodedTime prExplodedTime;
|
||||
PR_ExplodeTime(prTime, PR_GMTParameters, &prExplodedTime);
|
||||
|
||||
mozilla::DateTimeFormat::mLocale = new nsCString("en-US");
|
||||
mozilla::DateTimeFormat::DeleteCache();
|
||||
AppDateTimeFormat::mLocale = new nsCString("en-US");
|
||||
AppDateTimeFormat::DeleteCache();
|
||||
|
||||
nsAutoString formattedTime;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::yyyyMM, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01/1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::yyyyMMMM, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.year = Some(DateTimeFormat::Numeric::Numeric);
|
||||
components.month = Some(DateTimeFormat::Month::TwoDigit);
|
||||
|
||||
rv = mozilla::DateTimeFormat::GetCalendarSymbol(
|
||||
mozilla::DateTimeFormat::Field::Month,
|
||||
mozilla::DateTimeFormat::Style::Wide, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01/1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.year = Some(DateTimeFormat::Numeric::Numeric);
|
||||
components.month = Some(DateTimeFormat::Month::Long);
|
||||
|
||||
rv = mozilla::DateTimeFormat::GetCalendarSymbol(
|
||||
mozilla::DateTimeFormat::Field::Weekday,
|
||||
mozilla::DateTimeFormat::Style::Abbreviated, &prExplodedTime,
|
||||
formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Thu", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January 1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.month = Some(DateTimeFormat::Month::Long);
|
||||
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("January", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.weekday = Some(DateTimeFormat::Text::Short);
|
||||
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Thu", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
||||
TEST(AppDateTimeFormat, FormatPRExplodedTimeForeign)
|
||||
{
|
||||
PRTime prTime = 0;
|
||||
PRExplodedTime prExplodedTime;
|
||||
PR_ExplodeTime(prTime, PR_GMTParameters, &prExplodedTime);
|
||||
|
||||
mozilla::DateTimeFormat::mLocale = new nsCString("de-DE");
|
||||
mozilla::DateTimeFormat::DeleteCache();
|
||||
AppDateTimeFormat::mLocale = new nsCString("de-DE");
|
||||
AppDateTimeFormat::DeleteCache();
|
||||
StyleBag style = ToStyleBag(Some(Style::Long), Some(Style::Long));
|
||||
|
||||
nsAutoString formattedTime;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("1.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound);
|
||||
|
@ -138,8 +165,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
formattedTime.Find("00:00:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 19, 0, 1, 0, 1970, 4, 0, {(19 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("1.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound);
|
||||
|
@ -149,8 +175,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
|
||||
prExplodedTime = {0, 0, 0, 7, 1,
|
||||
0, 1970, 4, 0, {(6 * 60 * 60), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("1.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound);
|
||||
|
@ -161,8 +186,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
prExplodedTime = {
|
||||
0, 0, 29, 11, 1,
|
||||
0, 1970, 4, 0, {(10 * 60 * 60) + (29 * 60), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("1.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Januar") != kNotFound);
|
||||
|
@ -171,8 +195,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
formattedTime.Find("11:29:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 37, 23, 31, 11, 1969, 3, 364, {-(23 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("31.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound);
|
||||
|
@ -181,8 +204,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
formattedTime.Find("23:37:00") != kNotFound);
|
||||
|
||||
prExplodedTime = {0, 0, 0, 17, 31, 11, 1969, 3, 364, {-(7 * 60 * 60), 0}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("31.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound);
|
||||
|
@ -193,8 +215,7 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
prExplodedTime = {
|
||||
0, 0, 47, 14, 31,
|
||||
11, 1969, 3, 364, {-((10 * 60 * 60) + (13 * 60)), (1 * 60 * 60)}};
|
||||
rv = mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, kTimeFormatLong, &prExplodedTime, formattedTime);
|
||||
rv = AppDateTimeFormat::Format(style, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_TRUE(formattedTime.Find("31.") != kNotFound);
|
||||
ASSERT_TRUE(formattedTime.Find("Dezember") != kNotFound);
|
||||
|
@ -203,48 +224,72 @@ TEST(DateTimeFormat, FormatPRExplodedTimeForeign)
|
|||
formattedTime.Find("14:47:00") != kNotFound);
|
||||
}
|
||||
|
||||
TEST(DateTimeFormat, DateFormatSelectorsForeign)
|
||||
TEST(AppDateTimeFormat, DateFormatSelectorsForeign)
|
||||
{
|
||||
PRTime prTime = 0;
|
||||
PRExplodedTime prExplodedTime;
|
||||
PR_ExplodeTime(prTime, PR_GMTParameters, &prExplodedTime);
|
||||
|
||||
mozilla::DateTimeFormat::mLocale = new nsCString("de-DE");
|
||||
mozilla::DateTimeFormat::DeleteCache();
|
||||
AppDateTimeFormat::mLocale = new nsCString("de-DE");
|
||||
AppDateTimeFormat::DeleteCache();
|
||||
|
||||
nsAutoString formattedTime;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::yyyyMM, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01.1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.year = Some(DateTimeFormat::Numeric::Numeric);
|
||||
components.month = Some(DateTimeFormat::Month::TwoDigit);
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::yyyyMMMM, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Januar 1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("01.1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.year = Some(DateTimeFormat::Numeric::Numeric);
|
||||
components.month = Some(DateTimeFormat::Month::Long);
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::E, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Do", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Januar 1970", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.weekday = Some(DateTimeFormat::Text::Short);
|
||||
|
||||
rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&prExplodedTime, DateTimeFormat::Skeleton::EEEE, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Donnerstag", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Do", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.weekday = Some(DateTimeFormat::Text::Long);
|
||||
|
||||
rv = mozilla::DateTimeFormat::GetCalendarSymbol(
|
||||
mozilla::DateTimeFormat::Field::Month,
|
||||
mozilla::DateTimeFormat::Style::Wide, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Januar", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Donnerstag", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.month = Some(DateTimeFormat::Month::Long);
|
||||
|
||||
rv = mozilla::DateTimeFormat::GetCalendarSymbol(
|
||||
mozilla::DateTimeFormat::Field::Weekday,
|
||||
mozilla::DateTimeFormat::Style::Abbreviated, &prExplodedTime,
|
||||
formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Do", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Januar", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
{
|
||||
ComponentsBag components{};
|
||||
components.weekday = Some(DateTimeFormat::Text::Short);
|
||||
|
||||
nsresult rv =
|
||||
AppDateTimeFormat::Format(components, &prExplodedTime, formattedTime);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
ASSERT_STREQ("Do", NS_ConvertUTF16toUTF8(formattedTime).get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace mozilla::intl
|
|
@ -5,7 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"TestDateTimeFormat.cpp",
|
||||
"TestAppDateTimeFormat.cpp",
|
||||
"TestLocaleService.cpp",
|
||||
"TestLocaleServiceNegotiate.cpp",
|
||||
"TestOSPreferences.cpp",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "nsLayoutStatics.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "MediaManager.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||
#include "nsAttrValue.h"
|
||||
|
@ -391,7 +391,7 @@ void nsLayoutStatics::Shutdown() {
|
|||
nsHyphenationManager::Shutdown();
|
||||
nsDOMMutationObserver::Shutdown();
|
||||
|
||||
DateTimeFormat::Shutdown();
|
||||
mozilla::intl::AppDateTimeFormat::Shutdown();
|
||||
|
||||
ContentParent::ShutDown();
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#include "nsPageSequenceFrame.h"
|
||||
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/PrintedSheetFrame.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/StaticPresData.h"
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -387,8 +387,11 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
nsAutoString formattedDateString;
|
||||
PRTime now = PR_Now();
|
||||
if (NS_SUCCEEDED(DateTimeFormat::FormatPRTime(
|
||||
kDateFormatShort, kTimeFormatShort, now, formattedDateString))) {
|
||||
mozilla::intl::DateTimeFormat::StyleBag style;
|
||||
style.date = Some(mozilla::intl::DateTimeFormat::Style::Short);
|
||||
style.time = Some(mozilla::intl::DateTimeFormat::Style::Short);
|
||||
if (NS_SUCCEEDED(mozilla::intl::AppDateTimeFormat::Format(
|
||||
style, now, formattedDateString))) {
|
||||
SetDateTimeStr(formattedDateString);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
#include "nsIndexedToHTML.h"
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "netCore.h"
|
||||
|
@ -617,22 +617,24 @@ nsIndexedToHTML::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInput,
|
|||
return mParser->OnDataAvailable(aRequest, aInput, aOffset, aCount);
|
||||
}
|
||||
|
||||
static nsresult FormatTime(const nsDateFormatSelector aDateFormatSelector,
|
||||
const nsTimeFormatSelector aTimeFormatSelector,
|
||||
static nsresult FormatTime(const mozilla::intl::DateTimeFormat::Style& aStyle,
|
||||
const PRTime aPrTime, nsAString& aStringOut) {
|
||||
mozilla::intl::DateTimeFormat::StyleBag styleBag;
|
||||
styleBag.date = Some(aStyle);
|
||||
|
||||
// FormatPRExplodedTime will use GMT based formatted string (e.g. GMT+1)
|
||||
// instead of local time zone name (e.g. CEST).
|
||||
// To avoid this case when ResistFingerprinting is disabled, use
|
||||
// |FormatPRTime| to show exact time zone name.
|
||||
if (!nsContentUtils::ShouldResistFingerprinting()) {
|
||||
return mozilla::DateTimeFormat::FormatPRTime(
|
||||
aDateFormatSelector, aTimeFormatSelector, aPrTime, aStringOut);
|
||||
return mozilla::intl::AppDateTimeFormat::Format(styleBag, aPrTime,
|
||||
aStringOut);
|
||||
}
|
||||
|
||||
PRExplodedTime prExplodedTime;
|
||||
PR_ExplodeTime(aPrTime, PR_GMTParameters, &prExplodedTime);
|
||||
return mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
aDateFormatSelector, aTimeFormatSelector, &prExplodedTime, aStringOut);
|
||||
return mozilla::intl::AppDateTimeFormat::Format(styleBag, &prExplodedTime,
|
||||
aStringOut);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -781,10 +783,10 @@ nsIndexedToHTML::OnIndexAvailable(nsIRequest* aRequest, nsIDirIndex* aIndex) {
|
|||
pushBuffer.AppendInt(static_cast<int64_t>(t));
|
||||
pushBuffer.AppendLiteral("\">");
|
||||
nsAutoString formatted;
|
||||
FormatTime(kDateFormatShort, kTimeFormatNone, t, formatted);
|
||||
FormatTime(mozilla::intl::DateTimeFormat::Style::Short, t, formatted);
|
||||
AppendNonAsciiToNCR(formatted, pushBuffer);
|
||||
pushBuffer.AppendLiteral("</td>\n <td>");
|
||||
FormatTime(kDateFormatNone, kTimeFormatLong, t, formatted);
|
||||
FormatTime(mozilla::intl::DateTimeFormat::Style::Long, t, formatted);
|
||||
// use NCR to show date in any doc charset
|
||||
AppendNonAsciiToNCR(formatted, pushBuffer);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "TransportSecurityInfo.h"
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "PSMRunnable.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
|
|
@ -89,32 +89,35 @@ X509CertValidity::GetNotBefore(PRTime* aNotBefore) {
|
|||
|
||||
nsresult X509CertValidity::FormatTime(
|
||||
const PRTime& aTimeDate, PRTimeParamFn aParamFn,
|
||||
const nsTimeFormatSelector aTimeFormatSelector,
|
||||
const Maybe<intl::DateTimeFormat::Style> aTimeStyle,
|
||||
nsAString& aFormattedTimeDate) {
|
||||
if (!mTimesInitialized) return NS_ERROR_FAILURE;
|
||||
|
||||
PRExplodedTime explodedTime;
|
||||
PR_ExplodeTime(const_cast<PRTime&>(aTimeDate), aParamFn, &explodedTime);
|
||||
return mozilla::DateTimeFormat::FormatPRExplodedTime(
|
||||
kDateFormatLong, aTimeFormatSelector, &explodedTime, aFormattedTimeDate);
|
||||
intl::DateTimeFormat::StyleBag style;
|
||||
style.time = aTimeStyle;
|
||||
return intl::AppDateTimeFormat::Format(style, &explodedTime,
|
||||
aFormattedTimeDate);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotBeforeLocalTime(nsAString& aNotBeforeLocalTime) {
|
||||
return FormatTime(mNotBefore, PR_LocalTimeParameters, kTimeFormatLong,
|
||||
return FormatTime(mNotBefore, PR_LocalTimeParameters,
|
||||
Some(intl::DateTimeFormat::Style::Long),
|
||||
aNotBeforeLocalTime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotBeforeLocalDay(nsAString& aNotBeforeLocalDay) {
|
||||
return FormatTime(mNotBefore, PR_LocalTimeParameters, kTimeFormatNone,
|
||||
return FormatTime(mNotBefore, PR_LocalTimeParameters, Nothing(),
|
||||
aNotBeforeLocalDay);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotBeforeGMT(nsAString& aNotBeforeGMT) {
|
||||
return FormatTime(mNotBefore, PR_GMTParameters, kTimeFormatLong,
|
||||
aNotBeforeGMT);
|
||||
return FormatTime(mNotBefore, PR_GMTParameters,
|
||||
Some(intl::DateTimeFormat::Style::Long), aNotBeforeGMT);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -131,17 +134,19 @@ X509CertValidity::GetNotAfter(PRTime* aNotAfter) {
|
|||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotAfterLocalTime(nsAString& aNotAfterLocaltime) {
|
||||
return FormatTime(mNotAfter, PR_LocalTimeParameters, kTimeFormatLong,
|
||||
return FormatTime(mNotAfter, PR_LocalTimeParameters,
|
||||
Some(intl::DateTimeFormat::Style::Long),
|
||||
aNotAfterLocaltime);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotAfterLocalDay(nsAString& aNotAfterLocalDay) {
|
||||
return FormatTime(mNotAfter, PR_LocalTimeParameters, kTimeFormatNone,
|
||||
return FormatTime(mNotAfter, PR_LocalTimeParameters, Nothing(),
|
||||
aNotAfterLocalDay);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
X509CertValidity::GetNotAfterGMT(nsAString& aNotAfterGMT) {
|
||||
return FormatTime(mNotAfter, PR_GMTParameters, kTimeFormatLong, aNotAfterGMT);
|
||||
return FormatTime(mNotAfter, PR_GMTParameters,
|
||||
Some(intl::DateTimeFormat::Style::Long), aNotAfterGMT);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
#ifndef X509CertValidity_h
|
||||
#define X509CertValidity_h
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "mozpkix/Input.h"
|
||||
#include "nsIX509CertValidity.h"
|
||||
#include "prtime.h"
|
||||
|
||||
class X509CertValidity : public nsIX509CertValidity {
|
||||
public:
|
||||
|
@ -23,9 +24,10 @@ class X509CertValidity : public nsIX509CertValidity {
|
|||
virtual ~X509CertValidity() = default;
|
||||
|
||||
private:
|
||||
nsresult FormatTime(const PRTime& aTime, PRTimeParamFn aParamFn,
|
||||
const mozilla::nsTimeFormatSelector aTimeFormatSelector,
|
||||
nsAString& aFormattedTimeDate);
|
||||
nsresult FormatTime(
|
||||
const PRTime& aTime, PRTimeParamFn aParamFn,
|
||||
const mozilla::Maybe<mozilla::intl::DateTimeFormat::Style> aTimeStyle,
|
||||
nsAString& aFormattedTimeDate);
|
||||
|
||||
PRTime mNotBefore;
|
||||
PRTime mNotAfter;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "nsFaviconService.h"
|
||||
#include "nsPlacesMacros.h"
|
||||
#include "nsPlacesTriggers.h"
|
||||
#include "DateTimeFormat.h"
|
||||
#include "mozilla/intl/AppDateTimeFormat.h"
|
||||
#include "History.h"
|
||||
#include "Helpers.h"
|
||||
#include "NotifyRankingChanged.h"
|
||||
|
@ -3080,9 +3080,11 @@ void nsNavHistory::GetStringFromName(const char* aName, nsACString& aResult) {
|
|||
void nsNavHistory::GetMonthName(const PRExplodedTime& aTime,
|
||||
nsACString& aResult) {
|
||||
nsAutoString month;
|
||||
nsresult rv = mozilla::DateTimeFormat::GetCalendarSymbol(
|
||||
mozilla::DateTimeFormat::Field::Month,
|
||||
mozilla::DateTimeFormat::Style::Wide, &aTime, month);
|
||||
|
||||
mozilla::intl::DateTimeFormat::ComponentsBag components;
|
||||
components.month = Some(mozilla::intl::DateTimeFormat::Month::Long);
|
||||
nsresult rv =
|
||||
mozilla::intl::AppDateTimeFormat::Format(components, &aTime, month);
|
||||
if (NS_FAILED(rv)) {
|
||||
aResult = nsPrintfCString("[%d]", aTime.tm_month + 1);
|
||||
return;
|
||||
|
@ -3094,8 +3096,11 @@ void nsNavHistory::GetMonthName(const PRExplodedTime& aTime,
|
|||
void nsNavHistory::GetMonthYear(const PRExplodedTime& aTime,
|
||||
nsACString& aResult) {
|
||||
nsAutoString monthYear;
|
||||
nsresult rv = mozilla::DateTimeFormat::FormatDateTime(
|
||||
&aTime, DateTimeFormat::Skeleton::yyyyMMMM, monthYear);
|
||||
mozilla::intl::DateTimeFormat::ComponentsBag components;
|
||||
components.month = Some(mozilla::intl::DateTimeFormat::Month::Long);
|
||||
components.year = Some(mozilla::intl::DateTimeFormat::Numeric::Numeric);
|
||||
nsresult rv =
|
||||
mozilla::intl::AppDateTimeFormat::Format(components, &aTime, monthYear);
|
||||
if (NS_FAILED(rv)) {
|
||||
aResult = nsPrintfCString("[%d-%d]", aTime.tm_month + 1, aTime.tm_year);
|
||||
return;
|
||||
|
|
Загрузка…
Ссылка в новой задаче