• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (c) 2021 Huawei Device Co., Ltd.
3   * Licensed under the Apache License, Version 2.0 (the "License");
4   * you may not use this file except in compliance with the License.
5   * You may obtain a copy of the License at
6   *
7   *     http://www.apache.org/licenses/LICENSE-2.0
8   *
9   * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  #ifndef ECMASCRIPT_JS_DATE_TIME_FORMAT_H
17  #define ECMASCRIPT_JS_DATE_TIME_FORMAT_H
18  
19  #include "ecmascript/js_locale.h"
20  
21  namespace panda::ecmascript {
22  enum class CalendarOption : uint8_t { UNDEFINED = 0x01 };
23  enum class DateTimeStyleOption : uint8_t { FULL = 0x01, LONG, MEDIUM, SHORT, UNDEFINED, EXCEPTION };
24  enum class DefaultsOption : uint8_t { DATE = 0x01, TIME, ALL };
25  enum class HourCycleOption : uint8_t { H11 = 0x01, H12, H23, H24, UNDEFINED, EXCEPTION };
26  enum class RequiredOption : uint8_t { DATE = 0x01, TIME, ANY };
27  enum class Value : uint8_t { SHARED, START_RANGE, END_RANGE };
28  enum class IcuCacheType : uint8_t {NOT_CACHE, DEFAULT, DATE, TIME};
29  
30  constexpr int CAPACITY_3 = 3;
31  constexpr int CAPACITY_4 = 4;
32  constexpr int CAPACITY_5 = 5;
33  constexpr int CAPACITY_8 = 8;
34  constexpr int STRING_LENGTH_2 = 2;
35  constexpr int STRING_LENGTH_3 = 3;
36  constexpr int STRING_LENGTH_7 = 7;
37  constexpr int STRING_LENGTH_8 = 8;
38  constexpr int STRING_LENGTH_9 = 9;
39  constexpr int STRING_LENGTH_10 = 10;
40  
41  class IcuPatternDesc;
42  
43  std::vector<IcuPatternDesc> BuildIcuPatternDescs();
44  std::vector<IcuPatternDesc> InitializePattern(const IcuPatternDesc &hourData);
45  
46  using IcuPatternDescVect = std::vector<IcuPatternDesc>;
47  using IcuPatternEntry = std::pair<std::string, std::string>;
48  
49  class IcuPatternDesc {
50  public:
IcuPatternDesc(std::string property,const std::vector<IcuPatternEntry> & pairs,std::vector<std::string> allowedValues)51      IcuPatternDesc(std::string property, const std::vector<IcuPatternEntry> &pairs,
52                     std::vector<std::string> allowedValues) : property(std::move(property)), pairs(std::move(pairs)),
53                                                               allowedValues(std::move(allowedValues))
54      {
55          for (const auto &pair : pairs) {
56              map.emplace(pair.second, pair.first);
57          }
58      }
59  
60      virtual ~IcuPatternDesc() = default;
61  
62      std::string property;   // NOLINT(misc-non-private-member-variables-in-classes)
63      std::vector<IcuPatternEntry> pairs; // NOLINT(misc-non-private-member-variables-in-classes)
64      std::map<const std::string, const std::string> map; // NOLINT(misc-non-private-member-variables-in-classes)
65      std::vector<std::string> allowedValues; // NOLINT(misc-non-private-member-variables-in-classes)
66  
67      DEFAULT_COPY_SEMANTIC(IcuPatternDesc);
68      // NOLINT(performance-noexcept-move-constructor, hicpp-noexcept-move)
69      DEFAULT_NOEXCEPT_MOVE_SEMANTIC(IcuPatternDesc);
70  };
71  
72  class Pattern {
73  public:
Pattern(const std::string & data1,const std::string & data2)74      Pattern(const std::string &data1, const std::string &data2) : data(InitializePattern(
75          IcuPatternDesc("hour", {{data1, "2-digit"}, {data2, "numeric"}}, {"2-digit", "numeric"}))) {}
76      virtual ~Pattern() = default;
Get()77      std::vector<IcuPatternDesc> Get() const
78      {
79          return data;
80      }
81  
82  private:
83      std::vector<IcuPatternDesc> data{};
84      NO_COPY_SEMANTIC(Pattern);
85      NO_MOVE_SEMANTIC(Pattern);
86  };
87  
88  class JSDateTimeFormat : public JSObject {
89  public:
90      CAST_CHECK(JSDateTimeFormat, IsJSDateTimeFormat);
91  
92      static constexpr size_t LOCALE_OFFSET = JSObject::SIZE;
93      ACCESSORS(Locale, LOCALE_OFFSET, CALENDAR_OFFSET)
94      ACCESSORS(Calendar, CALENDAR_OFFSET, NUMBER_STRING_SYSTEM_OFFSET)
95      ACCESSORS(NumberingSystem, NUMBER_STRING_SYSTEM_OFFSET, TIME_ZONE_OFFSET)
96      ACCESSORS(TimeZone, TIME_ZONE_OFFSET, LOCALE_ICU_OFFSET)
97      ACCESSORS(LocaleIcu, LOCALE_ICU_OFFSET, SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET)
98      ACCESSORS(SimpleDateTimeFormatIcu, SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET, ISO8601_OFFSET)
99      ACCESSORS(Iso8601, ISO8601_OFFSET, BOUND_FORMAT_OFFSET)
100      ACCESSORS(BoundFormat, BOUND_FORMAT_OFFSET, BIT_FIELD_OFFSET)
101      ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
102      DEFINE_ALIGN_SIZE(LAST_OFFSET);
103  
104      // define BitField
105      static constexpr size_t HONOR_CYCLE_BITS = 3;
106      static constexpr size_t DATE_STYLE_BITS = 3;
107      static constexpr size_t TIME_STYLE_BITS = 3;
108      FIRST_BIT_FIELD(BitField, HourCycle, HourCycleOption, HONOR_CYCLE_BITS)
109      NEXT_BIT_FIELD(BitField, DateStyle, DateTimeStyleOption, DATE_STYLE_BITS, HourCycle)
110      NEXT_BIT_FIELD(BitField, TimeStyle, DateTimeStyleOption, TIME_STYLE_BITS, DateStyle)
111  
112      DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, BIT_FIELD_OFFSET)
113      DECL_DUMP()
114  
115      icu::Locale *GetIcuLocale() const;
116      static void SetIcuLocale(JSThread *thread, JSHandle<JSDateTimeFormat> obj,
117          const icu::Locale &icuLocale, const DeleteEntryPoint &callback);
118      static void FreeIcuLocale(void *pointer, void *data);
119  
120      icu::SimpleDateFormat *GetIcuSimpleDateFormat() const;
121      static void SetIcuSimpleDateFormat(JSThread *thread, JSHandle<JSDateTimeFormat> obj,
122          const icu::SimpleDateFormat &icuSimpleDateTimeFormat, const DeleteEntryPoint &callback);
123      static void FreeSimpleDateFormat(void *pointer, void *data);
124      static icu::SimpleDateFormat *GetCachedIcuSimpleDateFormat(JSThread *thread,
125                                                                 const JSHandle<JSTaggedValue> &locales,
126                                                                 IcuFormatterType type);
127  
128      // 13.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options)
129      static JSHandle<JSDateTimeFormat> InitializeDateTimeFormat(JSThread *thread,
130                                                                 const JSHandle<JSDateTimeFormat> &dateTimeFormat,
131                                                                 const JSHandle<JSTaggedValue> &locales,
132                                                                 const JSHandle<JSTaggedValue> &options,
133                                                                 IcuCacheType type = IcuCacheType::NOT_CACHE);
134  
135      // 13.1.2 ToDateTimeOptions (options, required, defaults)
136      static JSHandle<JSObject> ToDateTimeOptions(JSThread *thread, const JSHandle<JSTaggedValue> &options,
137                                                  const RequiredOption &required, const DefaultsOption &defaults);
138  
139      // 13.1.7 FormatDateTime(dateTimeFormat, x)
140      static JSHandle<EcmaString> FormatDateTime(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
141                                                 double x);
142      static JSHandle<EcmaString> FormatDateTime(JSThread *thread, const icu::SimpleDateFormat *simpleDateFormat,
143                                                 double x);
144  
145      // 13.1.8 FormatDateTimeToParts (dateTimeFormat, x)
146      static JSHandle<JSArray> FormatDateTimeToParts(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
147                                                     double x);
148  
149      // 13.1.10 UnwrapDateTimeFormat(dtf)
150      static JSHandle<JSTaggedValue> UnwrapDateTimeFormat(JSThread *thread,
151                                                          const JSHandle<JSTaggedValue> &dateTimeFormat);
152  
153      static JSHandle<TaggedArray> GainAvailableLocales(JSThread *thread);
154  
155      static void ResolvedOptions(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
156                                  const JSHandle<JSObject> &options);
157  
158      static JSHandle<EcmaString> NormDateTimeRange(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf, double x,
159                                                      double y);
160  
161      static JSHandle<JSArray> NormDateTimeRangeToParts(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf,
162                                                          double x, double y);
163  
164  private:
165      static HourCycleOption OptionToHourCycle(const std::string &hc);
166      // 2: number of elements
167      static Value TrackValue(int32_t beginning, int32_t ending, std::array<int32_t, 2> begin,
168                              std::array<int32_t, 2> end); // 2: number of elements
169  
170      static HourCycleOption OptionToHourCycle(UDateFormatHourCycle hc);
171  
172      static std::string ToHourCycleString(HourCycleOption hc);
173  
174      static std::unique_ptr<icu::TimeZone> ConstructTimeZone(const std::string &timezone);
175  
176      static std::string ConstructFormattedTimeZoneID(const std::string &input);
177  
178      static std::string ToTitleCaseTimezonePosition(const std::string &input);
179  
180      static std::unique_ptr<icu::DateIntervalFormat> ConstructDateIntervalFormat(const JSHandle<JSDateTimeFormat> &dtf);
181  
182      static std::string ConstructGMTTimeZoneID(const std::string &input);
183  
184      static std::unique_ptr<icu::Calendar> BuildCalendar(const icu::Locale &locale, const icu::TimeZone &timeZone);
185  
186      static std::map<std::string, std::string> GetSpecialTimeZoneMap();
187  
188      static JSHandle<JSArray> ConstructFDateIntervalToJSArray(JSThread *thread,
189                                                               const icu::FormattedDateInterval &formatted);
190  
191      static std::vector<IcuPatternDesc> GetIcuPatternDesc(const HourCycleOption &hourCycle);
192  
193      static std::unique_ptr<icu::SimpleDateFormat> CreateICUSimpleDateFormat(const icu::Locale &icuLocale,
194                                                                 const icu::UnicodeString &skeleton,
195                                                                 icu::DateTimePatternGenerator *generator,
196                                                                 HourCycleOption hc);
197  
198      static JSHandle<JSTaggedValue> ConvertFieldIdToDateType(JSThread *thread, int32_t fieldId);
199  
200      static icu::UnicodeString ChangeHourCyclePattern(const icu::UnicodeString &pattern, HourCycleOption hc);
201  
202      static std::string ToTitleCaseFunction(const std::string &input);
203  
204      static bool IsValidTimeZoneInput(const std::string &input);
205  
206      static JSHandle<EcmaString> ToValueString(JSThread *thread, Value value);
207  
208      static icu::FormattedDateInterval ConstructDTFRange(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf,
209                                                          double x, double y);
210  };
211  }  // namespace panda::ecmascript
212  #endif  // ECMASCRIPT_JS_DATE_TIME_FORMAT_H
213