chromium/v8/src/objects/js-date-time-format.cc

// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/objects/js-date-time-format.h"

#include <algorithm>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "src/base/bit-field.h"
#include "src/date/date.h"
#include "src/execution/isolate.h"
#include "src/heap/factory.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-date-time-format-inl.h"
#include "src/objects/js-temporal-objects-inl.h"
#include "src/objects/managed-inl.h"
#include "src/objects/option-utils.h"
#include "unicode/calendar.h"
#include "unicode/dtitvfmt.h"
#include "unicode/dtptngen.h"
#include "unicode/fieldpos.h"
#include "unicode/gregocal.h"
#include "unicode/smpdtfmt.h"
#include "unicode/unistr.h"

#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif  // V8_INTL_SUPPORT

namespace v8::internal {

namespace  // namespace

// Return the time zone id which match ICU's expectation of title casing
// return empty string when error.
std::string JSDateTimeFormat::CanonicalizeTimeZoneID(const std::string& input) {}

namespace {
Handle<String> DateTimeStyleAsString(Isolate* isolate,
                                     JSDateTimeFormat::DateTimeStyle style) {}

int FractionalSecondDigitsFromPattern(const std::string& pattern) {}
}  // namespace

MaybeHandle<String> JSDateTimeFormat::TimeZoneIdToString(
    Isolate* isolate, const icu::UnicodeString& id) {}

Handle<Object> JSDateTimeFormat::TimeZoneId(Isolate* isolate,
                                            const icu::TimeZone& tz) {}

namespace {
Handle<String> GetCalendar(Isolate* isolate,
                           const icu::SimpleDateFormat& simple_date_format) {}

Handle<Object> GetTimeZone(Isolate* isolate,
                           const icu::SimpleDateFormat& simple_date_format) {}
}  // namespace

Handle<String> JSDateTimeFormat::Calendar(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format) {}

Handle<Object> JSDateTimeFormat::TimeZone(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format) {}

// ecma402 #sec-intl.datetimeformat.prototype.resolvedoptions
MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format) {}

namespace {

// #sec-temporal-istemporalobject
bool IsTemporalObject(DirectHandle<Object> value) {}

// #sec-temporal-sametemporaltype
bool SameTemporalType(DirectHandle<Object> x, DirectHandle<Object> y) {}

enum class PatternKind {};
struct DateTimeValueRecord {};

DateTimeValueRecord TemporalInstantToRecord(
    Isolate* isolate, DirectHandle<JSTemporalInstant> instant,
    PatternKind kind) {}

Maybe<DateTimeValueRecord> TemporalPlainDateTimeToRecord(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    PatternKind kind, Handle<JSTemporalPlainDateTime> plain_date_time,
    const char* method_name) {}

template <typename T>
Maybe<DateTimeValueRecord> TemporalToRecord(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    PatternKind kind, Handle<T> temporal, Handle<JSReceiver> calendar,
    const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporaldate
Maybe<DateTimeValueRecord> HandleDateTimeTemporalDate(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar,
    Handle<JSTemporalPlainDate> temporal_date, const char* method_name) {}
// #sec-temporal-handledatetimevaluetemporaldatetime
Maybe<DateTimeValueRecord> HandleDateTimeTemporalDateTime(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar,
    Handle<JSTemporalPlainDateTime> date_time, const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporalzoneddatetime
Maybe<DateTimeValueRecord> HandleDateTimeTemporalZonedDateTime(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar,
    DirectHandle<JSTemporalZonedDateTime> zoned_date_time,
    const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporalinstant
Maybe<DateTimeValueRecord> HandleDateTimeTemporalInstant(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    DirectHandle<JSTemporalInstant> instant, const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporaltime
Maybe<DateTimeValueRecord> HandleDateTimeTemporalTime(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    DirectHandle<JSTemporalPlainTime> temporal_time, const char* method_name) {}

template <typename T>
Maybe<DateTimeValueRecord> HandleDateTimeTemporalYearMonthOrMonthDay(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar, PatternKind kind,
    Handle<T> temporal, const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporalyearmonth
Maybe<DateTimeValueRecord> HandleDateTimeTemporalYearMonth(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar,
    Handle<JSTemporalPlainYearMonth> temporal_year_month,
    const char* method_name) {}

// #sec-temporal-handledatetimevaluetemporalmonthday
Maybe<DateTimeValueRecord> HandleDateTimeTemporalMonthDay(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar,
    Handle<JSTemporalPlainMonthDay> temporal_month_day,
    const char* method_name) {}

// #sec-temporal-handledatetimeothers
Maybe<DateTimeValueRecord> HandleDateTimeOthers(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<Object> x_obj, const char* method_name) {}

// #sec-temporal-handledatetimevalue
Maybe<DateTimeValueRecord> HandleDateTimeValue(
    Isolate* isolate, const icu::SimpleDateFormat& date_time_format,
    Handle<String> date_time_format_calendar, Handle<Object> x,
    const char* method_name) {}

// This helper function handles Supported fields and Default fields in Table 16
// ( #table-temporal-patterns ).  It remove all the fields not stated in keep
// from input, and add the fields in add_default if a skeleton in the same
// category is in the input, with considering the equivalent.
// For example, if input is "yyyyMMhm", keep is {y,M,d} and add_default is
// {y,M,d}, the output will be "yyyyMMd". For example, if input is
// "yyyyMMhmOOOO", keep is {h,m,s,z,O,v} and add_default is {h,m,s}, then the
// output will be "hmOOOOs". The meaning of the skeleton letters is stated in
// UTS35
// https://www.unicode.org/reports/tr35/tr35-dates.html#table-date-field-symbol-table
icu::UnicodeString KeepSupportedAddDefault(
    const icu::UnicodeString& input, const std::set<char16_t>& keep,
    const std::set<char16_t>& add_default) {}

icu::UnicodeString GetSkeletonForPatternKind(const icu::UnicodeString& input,
                                             PatternKind kind) {}

icu::UnicodeString SkeletonFromDateFormat(
    const icu::SimpleDateFormat& icu_date_format) {}

std::unique_ptr<icu::SimpleDateFormat> GetSimpleDateTimeForTemporal(
    const icu::SimpleDateFormat& date_format, PatternKind kind) {}

icu::UnicodeString CallICUFormat(const icu::SimpleDateFormat& date_format,
                                 PatternKind kind, double time_in_milliseconds,
                                 icu::FieldPositionIterator* fp_iter,
                                 UErrorCode& status) {}

// ecma402/#sec-formatdatetime
// FormatDateTime( dateTimeFormat, x )
MaybeHandle<String> FormatDateTime(Isolate* isolate,
                                   const icu::SimpleDateFormat& date_format,
                                   double x) {}

MaybeHandle<String> FormatMillisecondsByKindToString(
    Isolate* isolate, const icu::SimpleDateFormat& date_format,
    PatternKind kind, double x) {}
MaybeHandle<String> FormatDateTimeWithTemporalSupport(
    Isolate* isolate, const icu::SimpleDateFormat& date_format,
    Handle<String> date_time_format_calendar, Handle<Object> x,
    const char* method_name) {}

MaybeHandle<String> FormatDateTimeWithTemporalSupport(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    Handle<Object> x, const char* method_name) {}

}  // namespace

// ecma402/#sec-datetime-format-functions
// DateTime Format Functions
MaybeHandle<String> JSDateTimeFormat::DateTimeFormat(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    Handle<Object> date, const char* method_name) {}

namespace {
Isolate::ICUObjectCacheType ConvertToCacheType(
    JSDateTimeFormat::DefaultsOption type) {}

}  // namespace

MaybeHandle<String> JSDateTimeFormat::ToLocaleDateTime(
    Isolate* isolate, Handle<Object> date, Handle<Object> locales,
    Handle<Object> options, RequiredOption required, DefaultsOption defaults,
    const char* method_name) {}

MaybeHandle<String> JSDateTimeFormat::TemporalToLocaleString(
    Isolate* isolate, Handle<JSReceiver> x, Handle<Object> locales,
    Handle<Object> options, const char* method_name) {}

MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::UnwrapDateTimeFormat(
    Isolate* isolate, Handle<JSReceiver> format_holder) {}

// Convert the input in the form of
// [+-\u2212]hh:?mm  to the ID acceptable for SimpleTimeZone
// GMT[+-]hh or GMT[+-]hh:mm or empty
std::optional<std::string> GetOffsetTimeZone(Isolate* isolate,
                                             Handle<String> time_zone) {}
std::unique_ptr<icu::TimeZone> JSDateTimeFormat::CreateTimeZone(
    Isolate* isolate, Handle<String> time_zone_string) {}

namespace {

class CalendarCache {};

icu::Calendar* CreateCalendar(Isolate* isolate, const icu::Locale& icu_locale,
                              icu::TimeZone* tz) {}

icu::UnicodeString ReplaceHourCycleInPattern(icu::UnicodeString pattern,
                                             JSDateTimeFormat::HourCycle hc) {}

std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormat(
    const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
    icu::DateTimePatternGenerator* generator, JSDateTimeFormat::HourCycle hc) {}

class DateFormatCache {};

std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormatFromCache(
    const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
    icu::DateTimePatternGenerator* generator, JSDateTimeFormat::HourCycle hc) {}

// We treat PatternKind::kDate different than other because most of the
// pre-existing usage are using the formatter with Date() and Temporal is
// new and not yet adopted by the web yet. We try to optimize the performance
// and memory usage for the pre-existing code so we cache for it.
// We may later consider caching Temporal one also if the usage increase.
// Right now we want to avoid making the constructor more expensive and
// increasing overhead in the object.
std::unique_ptr<icu::DateIntervalFormat> LazyCreateDateIntervalFormat(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    PatternKind kind) {}

JSDateTimeFormat::HourCycle HourCycleFromPattern(
    const icu::UnicodeString pattern) {}

icu::DateFormat::EStyle DateTimeStyleToEStyle(
    JSDateTimeFormat::DateTimeStyle style) {}

icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input,
                                   JSDateTimeFormat::HourCycle hc) {}

std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(
    JSDateTimeFormat::DateTimeStyle date_style,
    JSDateTimeFormat::DateTimeStyle time_style, icu::Locale& icu_locale,
    JSDateTimeFormat::HourCycle hc, icu::DateTimePatternGenerator* generator) {}

class DateTimePatternGeneratorCache {};

}  // namespace

enum FormatMatcherOption {};

// ecma402/#sec-initializedatetimeformat
MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
    Isolate* isolate, DirectHandle<Map> map, Handle<Object> locales,
    Handle<Object> input_options, const char* service) {}

MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::CreateDateTimeFormat(
    Isolate* isolate, DirectHandle<Map> map, Handle<Object> locales,
    Handle<Object> input_options, RequiredOption required,
    DefaultsOption defaults, const char* service) {}

namespace {

// The list comes from third_party/icu/source/i18n/unicode/udat.h.
// They're mapped to DateTimeFormat components listed at
// https://tc39.github.io/ecma402/#sec-datetimeformat-abstracts .
Handle<String> IcuDateFieldIdToDateType(int32_t field_id, Isolate* isolate) {}

MaybeHandle<JSArray> FieldPositionIteratorToArray(
    Isolate* isolate, const icu::UnicodeString& formatted,
    icu::FieldPositionIterator fp_iter, bool output_source);

MaybeHandle<JSArray> FormatMillisecondsByKindToArray(
    Isolate* isolate, const icu::SimpleDateFormat& date_format,
    PatternKind kind, double x, bool output_source) {}
MaybeHandle<JSArray> FormatMillisecondsByKindToArrayOutputSource(
    Isolate* isolate, const icu::SimpleDateFormat& date_format,
    PatternKind kind, double x) {}

MaybeHandle<JSArray> FormatToPartsWithTemporalSupport(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    Handle<Object> x, bool output_source, const char* method_name) {}

MaybeHandle<JSArray> FormatMillisecondsToArray(
    Isolate* isolate, const icu::SimpleDateFormat& format, double value,
    bool output_source) {}
MaybeHandle<JSArray> FormatMillisecondsToArrayOutputSource(
    Isolate* isolate, const icu::SimpleDateFormat& format, double value) {}
}  // namespace

MaybeHandle<JSArray> JSDateTimeFormat::FormatToParts(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    Handle<Object> x, bool output_source, const char* method_name) {}

namespace {
MaybeHandle<JSArray> FieldPositionIteratorToArray(
    Isolate* isolate, const icu::UnicodeString& formatted,
    icu::FieldPositionIterator fp_iter, bool output_source) {}

}  // namespace

const std::set<std::string>& JSDateTimeFormat::GetAvailableLocales() {}

Handle<String> JSDateTimeFormat::HourCycleAsString() const {}

namespace {

Maybe<bool> AddPartForFormatRange(
    Isolate* isolate, Handle<JSArray> array, const icu::UnicodeString& string,
    int32_t index, int32_t field, int32_t start, int32_t end,
    const Intl::FormatRangeSourceTracker& tracker) {}

// If this function return a value, it could be a throw of TypeError, or normal
// formatted string. If it return a nullopt the caller should call the fallback
// function.
std::optional<MaybeHandle<String>> FormattedToString(
    Isolate* isolate, const icu::FormattedValue& formatted) {}

// A helper function to convert the FormattedDateInterval to a
// MaybeHandle<JSArray> for the implementation of formatRangeToParts.
// If this function return a value, it could be a throw of TypeError, or normal
// formatted parts in JSArray. If it return a nullopt the caller should call
// the fallback function.
std::optional<MaybeHandle<JSArray>> FormattedDateIntervalToJSArray(
    Isolate* isolate, const icu::FormattedValue& formatted) {}

// The shared code between formatRange and formatRangeToParts
template <typename T, std::optional<MaybeHandle<T>> (*Format)(
                          Isolate*, const icu::FormattedValue&)>
std::optional<MaybeHandle<T>> CallICUFormatRange(
    Isolate* isolate, const icu::DateIntervalFormat* format,
    const icu::Calendar* calendar, double x, double y);
// #sec-partitiondatetimerangepattern
template <typename T, std::optional<MaybeHandle<T>> (*Format)(
                          Isolate*, const icu::FormattedValue&)>
std::optional<MaybeHandle<T>> PartitionDateTimeRangePattern(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format, double x,
    double y, const char* method_name) {}

template <typename T, std::optional<MaybeHandle<T>> (*Format)(
                          Isolate*, const icu::FormattedValue&)>
std::optional<MaybeHandle<T>> CallICUFormatRange(
    Isolate* isolate, const icu::DateIntervalFormat* format,
    const icu::Calendar* calendar, double x, double y) {}

template <typename T,
          std::optional<MaybeHandle<T>> (*Format)(Isolate*,
                                                  const icu::FormattedValue&),
          MaybeHandle<T> (*Fallback)(Isolate*, const icu::SimpleDateFormat&,
                                     PatternKind, double)>
MaybeHandle<T> FormatRangeCommonWithTemporalSupport(
    Isolate* isolate, DirectHandle<JSDateTimeFormat> date_time_format,
    Handle<Object> x_obj, Handle<Object> y_obj, const char* method_name) {}

template <typename T,
          std::optional<MaybeHandle<T>> (*Format)(Isolate*,
                                                  const icu::FormattedValue&),
          MaybeHandle<T> (*Fallback)(Isolate*, const icu::SimpleDateFormat&,
                                     double)>
MaybeHandle<T> FormatRangeCommon(Isolate* isolate,
                                 Handle<JSDateTimeFormat> date_time_format,
                                 Handle<Object> x_obj, Handle<Object> y_obj,
                                 const char* method_name) {}

}  // namespace

MaybeHandle<String> JSDateTimeFormat::FormatRange(
    Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
    Handle<Object> x, Handle<Object> y, const char* method_name) {}

MaybeHandle<JSArray> JSDateTimeFormat::FormatRangeToParts(
    Isolate* isolate, Handle<JSDateTimeFormat> date_time_format,
    Handle<Object> x, Handle<Object> y, const char* method_name) {}

}  // namespace v8::internal