• 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 icu::DateFormat::EStyle DateTimeStyleToEStyle(DateTimeStyleOption style);
46 HourCycleOption HourCycleFromPattern(const icu::UnicodeString pattern);
47 icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input, HourCycleOption hc);
48 std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(DateTimeStyleOption dateStyle,
49                                                             DateTimeStyleOption timeStyle,
50                                                             icu::Locale &icuLocale,
51                                                             HourCycleOption hc,
52                                                             icu::DateTimePatternGenerator *generator);
53 
54 using IcuPatternDescVect = std::vector<IcuPatternDesc>;
55 using IcuPatternEntry = std::pair<std::string, std::string>;
56 
57 class IcuPatternDesc {
58 public:
IcuPatternDesc(std::string property,const std::vector<IcuPatternEntry> & pairs,std::vector<std::string> allowedValues)59     IcuPatternDesc(std::string property, const std::vector<IcuPatternEntry> &pairs,
60                    std::vector<std::string> allowedValues) : property(std::move(property)), pairs(std::move(pairs)),
61                                                              allowedValues(std::move(allowedValues))
62     {
63         for (const auto &pair : pairs) {
64             map.emplace(pair.second, pair.first);
65         }
66     }
67 
68     virtual ~IcuPatternDesc() = default;
69 
70     std::string property;   // NOLINT(misc-non-private-member-variables-in-classes)
71     std::vector<IcuPatternEntry> pairs; // NOLINT(misc-non-private-member-variables-in-classes)
72     std::map<const std::string, const std::string> map; // NOLINT(misc-non-private-member-variables-in-classes)
73     std::vector<std::string> allowedValues; // NOLINT(misc-non-private-member-variables-in-classes)
74 
75     DEFAULT_COPY_SEMANTIC(IcuPatternDesc);
76     // NOLINT(performance-noexcept-move-constructor, hicpp-noexcept-move)
77     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(IcuPatternDesc);
78 };
79 
80 class Pattern {
81 public:
Pattern(const std::string & data1,const std::string & data2)82     Pattern(const std::string &data1, const std::string &data2) : data(InitializePattern(
83         IcuPatternDesc("hour", {{data1, "2-digit"}, {data2, "numeric"}}, {"2-digit", "numeric"}))) {}
84     virtual ~Pattern() = default;
Get()85     std::vector<IcuPatternDesc> Get() const
86     {
87         return data;
88     }
89 
90 private:
91     std::vector<IcuPatternDesc> data{};
92     NO_COPY_SEMANTIC(Pattern);
93     NO_MOVE_SEMANTIC(Pattern);
94 };
95 
96 class JSDateTimeFormat : public JSObject {
97 public:
98     CAST_CHECK(JSDateTimeFormat, IsJSDateTimeFormat);
99 
100     static constexpr size_t LOCALE_OFFSET = JSObject::SIZE;
101     ACCESSORS(Locale, LOCALE_OFFSET, CALENDAR_OFFSET)
102     ACCESSORS(Calendar, CALENDAR_OFFSET, NUMBER_STRING_SYSTEM_OFFSET)
103     ACCESSORS(NumberingSystem, NUMBER_STRING_SYSTEM_OFFSET, TIME_ZONE_OFFSET)
104     ACCESSORS(TimeZone, TIME_ZONE_OFFSET, LOCALE_ICU_OFFSET)
105     ACCESSORS(LocaleIcu, LOCALE_ICU_OFFSET, SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET)
106     ACCESSORS(SimpleDateTimeFormatIcu, SIMPLE_DATE_TIME_FORMAT_ICU_OFFSET, ISO8601_OFFSET)
107     ACCESSORS(Iso8601, ISO8601_OFFSET, BOUND_FORMAT_OFFSET)
108     ACCESSORS(BoundFormat, BOUND_FORMAT_OFFSET, BIT_FIELD_OFFSET)
109     ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
110     DEFINE_ALIGN_SIZE(LAST_OFFSET);
111 
112     // define BitField
113     static constexpr size_t HONOR_CYCLE_BITS = 3;
114     static constexpr size_t DATE_STYLE_BITS = 3;
115     static constexpr size_t TIME_STYLE_BITS = 3;
116     FIRST_BIT_FIELD(BitField, HourCycle, HourCycleOption, HONOR_CYCLE_BITS)
117     NEXT_BIT_FIELD(BitField, DateStyle, DateTimeStyleOption, DATE_STYLE_BITS, HourCycle)
118     NEXT_BIT_FIELD(BitField, TimeStyle, DateTimeStyleOption, TIME_STYLE_BITS, DateStyle)
119 
120     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, LOCALE_OFFSET, BIT_FIELD_OFFSET)
121     DECL_DUMP()
122 
123     icu::Locale *GetIcuLocale() const;
124     static void SetIcuLocale(JSThread *thread, JSHandle<JSDateTimeFormat> obj,
125         const icu::Locale &icuLocale, const DeleteEntryPoint &callback);
126     static void FreeIcuLocale(void *pointer, void *data);
127 
128     icu::SimpleDateFormat *GetIcuSimpleDateFormat() const;
129     static void SetIcuSimpleDateFormat(JSThread *thread, JSHandle<JSDateTimeFormat> obj,
130         const icu::SimpleDateFormat &icuSimpleDateTimeFormat, const DeleteEntryPoint &callback);
131     static void FreeSimpleDateFormat(void *pointer, void *data);
132     static icu::SimpleDateFormat *GetCachedIcuSimpleDateFormat(JSThread *thread,
133                                                                const JSHandle<JSTaggedValue> &locales,
134                                                                IcuFormatterType type);
135 
136     // 13.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options)
137     static JSHandle<JSDateTimeFormat> InitializeDateTimeFormat(JSThread *thread,
138                                                                const JSHandle<JSDateTimeFormat> &dateTimeFormat,
139                                                                const JSHandle<JSTaggedValue> &locales,
140                                                                const JSHandle<JSTaggedValue> &options,
141                                                                IcuCacheType type = IcuCacheType::NOT_CACHE);
142 
143     // 13.1.2 ToDateTimeOptions (options, required, defaults)
144     static JSHandle<JSObject> ToDateTimeOptions(JSThread *thread, const JSHandle<JSTaggedValue> &options,
145                                                 const RequiredOption &required, const DefaultsOption &defaults);
146 
147     // 13.1.7 FormatDateTime(dateTimeFormat, x)
148     static JSHandle<EcmaString> FormatDateTime(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
149                                                double x);
150     static JSHandle<EcmaString> FormatDateTime(JSThread *thread, const icu::SimpleDateFormat *simpleDateFormat,
151                                                double x);
152 
153     // 13.1.8 FormatDateTimeToParts (dateTimeFormat, x)
154     static JSHandle<JSArray> FormatDateTimeToParts(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
155                                                    double x);
156 
157     // 13.1.10 UnwrapDateTimeFormat(dtf)
158     static JSHandle<JSTaggedValue> UnwrapDateTimeFormat(JSThread *thread,
159                                                         const JSHandle<JSTaggedValue> &dateTimeFormat);
160 
161     static JSHandle<TaggedArray> GainAvailableLocales(JSThread *thread);
162 
163     static void ResolvedOptions(JSThread *thread, const JSHandle<JSDateTimeFormat> &dateTimeFormat,
164                                 const JSHandle<JSObject> &options);
165 
166     static JSHandle<EcmaString> NormDateTimeRange(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf, double x,
167                                                     double y);
168 
169     static JSHandle<JSArray> NormDateTimeRangeToParts(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf,
170                                                         double x, double y);
171 
172 private:
173     static HourCycleOption OptionToHourCycle(const std::string &hc);
174     // 2: number of elements
175     static Value TrackValue(int32_t beginning, int32_t ending, std::array<int32_t, 2> begin,
176                             std::array<int32_t, 2> end);
177 
178     static HourCycleOption OptionToHourCycle(UDateFormatHourCycle hc);
179 
180     static std::string ToHourCycleString(HourCycleOption hc);
181 
182     static std::unique_ptr<icu::TimeZone> ConstructTimeZone(const std::string &timezone);
183 
184     static std::string ConstructFormattedTimeZoneID(const std::string &input);
185 
186     static std::string ToTitleCaseTimezonePosition(const std::string &input);
187 
188     static std::unique_ptr<icu::DateIntervalFormat> ConstructDateIntervalFormat(const JSHandle<JSDateTimeFormat> &dtf);
189 
190     static std::string ConstructGMTTimeZoneID(const std::string &input);
191 
192     static std::unique_ptr<icu::Calendar> BuildCalendar(const icu::Locale &locale, const icu::TimeZone &timeZone);
193 
194     static std::map<std::string, std::string> GetSpecialTimeZoneMap();
195 
196     static JSHandle<JSArray> ConstructFDateIntervalToJSArray(JSThread *thread,
197                                                              const icu::FormattedDateInterval &formatted);
198 
199     static std::vector<IcuPatternDesc> GetIcuPatternDesc(const HourCycleOption &hourCycle);
200 
201     static std::unique_ptr<icu::SimpleDateFormat> CreateICUSimpleDateFormat(const icu::Locale &icuLocale,
202                                                                const icu::UnicodeString &skeleton,
203                                                                icu::DateTimePatternGenerator *generator,
204                                                                HourCycleOption hc);
205 
206     static JSHandle<JSTaggedValue> ConvertFieldIdToDateType(JSThread *thread, int32_t fieldId);
207 
208     static icu::UnicodeString ChangeHourCyclePattern(const icu::UnicodeString &pattern, HourCycleOption hc);
209 
210     static std::string ToTitleCaseFunction(const std::string &input);
211 
212     static bool IsValidTimeZoneInput(const std::string &input);
213 
214     static JSHandle<EcmaString> ToValueString(JSThread *thread, Value value);
215 
216     static icu::FormattedDateInterval ConstructDTFRange(JSThread *thread, const JSHandle<JSDateTimeFormat> &dtf,
217                                                         double x, double y);
218 };
219 }  // namespace panda::ecmascript
220 #endif  // ECMASCRIPT_JS_DATE_TIME_FORMAT_H
221