Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
#ifndef intl_components_DateTimePatternGenerator_h_
#define intl_components_DateTimePatternGenerator_h_
#include "unicode/udatpg.h"
#include "mozilla/EnumSet.h"
#include "mozilla/Result.h"
#include "mozilla/Span.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/intl/ICU4CGlue.h"
#include "mozilla/intl/ICUError.h"
namespace mozilla::intl {
class DisplayNames;
/**
* The DateTimePatternGenerator is the machinery used to work with DateTime
* pattern manipulation. It is expensive to create one, and so generally it is
* created once and then cached. It may be needed to be passed in as an argument
* for different mozilla::intl APIs.
*/
class DateTimePatternGenerator final {
public:
explicit DateTimePatternGenerator(UDateTimePatternGenerator* aGenerator)
: mGenerator(aGenerator) {
MOZ_ASSERT(aGenerator);
};
// Transfer ownership of the UDateTimePatternGenerator in the move
// constructor.
DateTimePatternGenerator(DateTimePatternGenerator&& other) noexcept;
// Transfer ownership of the UEnumeration in the move assignment operator.
DateTimePatternGenerator& operator=(
DateTimePatternGenerator&& other) noexcept;
// Disallow copy.
DateTimePatternGenerator(const DateTimePatternGenerator&) = delete;
DateTimePatternGenerator& operator=(const DateTimePatternGenerator&) = delete;
~DateTimePatternGenerator();
static Result<UniquePtr<DateTimePatternGenerator>, ICUError> TryCreate(
const char* aLocale);
enum class PatternMatchOption {
/**
* Adjust the 'hour' field in the resolved pattern to match the input
* skeleton width.
*/
HourField,
/**
* Adjust the 'minute' field in the resolved pattern to match the input
* skeleton width.
*/
MinuteField,
/**
* Adjust the 'second' field in the resolved pattern to match the input
* skeleton width.
*/
SecondField,
};
/**
* Given a skeleton (a string with unordered datetime fields), get a best
* pattern that will fit for that locale. This pattern will be filled into the
* buffer. e.g. The skeleton "yMd" would return the pattern "M/d/y" for en-US,
* or "dd/MM/y" for en-GB.
*/
template <typename B>
ICUResult GetBestPattern(Span<const char16_t> aSkeleton, B& aBuffer,
EnumSet<PatternMatchOption> options = {}) {
return FillBufferWithICUCall(
aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
return udatpg_getBestPatternWithOptions(
mGenerator.GetMut(), aSkeleton.data(),
static_cast<int32_t>(aSkeleton.Length()),
toUDateTimePatternMatchOptions(options), target, length, status);
});
}
/**
* Get a skeleton (a string with unordered datetime fields) from a pattern.
* For example, both "MMM-dd" and "dd/MMM" produce the skeleton "MMMdd".
*/
template <typename B>
static ICUResult GetSkeleton(Span<const char16_t> aPattern, B& aBuffer) {
// At one time udatpg_getSkeleton required a UDateTimePatternGenerator*, but
// now it is valid to pass in a nullptr.
return FillBufferWithICUCall(
aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
return udatpg_getSkeleton(nullptr, aPattern.data(),
static_cast<int32_t>(aPattern.Length()),
target, length, status);
});
}
/**
* Get a pattern of the form "{1} {0}" to combine separate date and time
* patterns into a single pattern. The "{0}" part is the placeholder for the
* time pattern and "{1}" is the placeholder for the date pattern.
*
* See dateTimeFormat from
*
* Note:
* In CLDR, it's called Date-Time Combined Format
*
* The naming 'placeholder pattern' is from ICU4X.
*/
Span<const char16_t> GetPlaceholderPattern() const {
int32_t length;
const char16_t* combined =
udatpg_getDateTimeFormat(mGenerator.GetConst(), &length);
return Span{combined, static_cast<size_t>(length)};
}
private:
// Allow other mozilla::intl components to access the underlying
// UDateTimePatternGenerator.
friend class DisplayNames;
UDateTimePatternGenerator* GetUDateTimePatternGenerator() {
return mGenerator.GetMut();
}
ICUPointer<UDateTimePatternGenerator> mGenerator =
ICUPointer<UDateTimePatternGenerator>(nullptr);
static UDateTimePatternMatchOptions toUDateTimePatternMatchOptions(
EnumSet<PatternMatchOption> options) {
struct OptionMap {
PatternMatchOption from;
UDateTimePatternMatchOptions to;
} static constexpr map[] = {
{PatternMatchOption::HourField, UDATPG_MATCH_HOUR_FIELD_LENGTH},
#ifndef U_HIDE_INTERNAL_API
{PatternMatchOption::MinuteField, UDATPG_MATCH_MINUTE_FIELD_LENGTH},
{PatternMatchOption::SecondField, UDATPG_MATCH_SECOND_FIELD_LENGTH},
#endif
};
UDateTimePatternMatchOptions result = UDATPG_MATCH_NO_OPTIONS;
for (const auto& entry : map) {
if (options.contains(entry.from)) {
result = UDateTimePatternMatchOptions(result | entry.to);
}
}
return result;
}
};
} // namespace mozilla::intl
#endif