• 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_JSDATE_H
17 #define ECMASCRIPT_JSDATE_H
18 
19 #include <array>
20 
21 #include "ecmascript/ecma_runtime_call_info.h"
22 #include "ecmascript/js_tagged_value-inl.h"
23 
24 namespace panda::ecmascript {
25 static constexpr int64_t DAYS_IN_YEAR = 365;
26 static constexpr std::array<int, 2> APPROXIMATION_NUMBER = {100000, 3652425};
27 static constexpr int64_t CHINA_BEFORE_1900_MS = -2177481943000;
28 static constexpr int64_t CHINA_1901_MS = -2177452800000;
29 static constexpr int CHINA_BEFORE_1901_ADDMS = 343000;
30 static constexpr int MS_PER_SECOND = 1000;
31 static constexpr int SEC_PER_MINUTE = 60;
32 static constexpr int SEC_PER_HOUR = 3600;
33 static constexpr int MIN_PER_HOUR = 60;
34 static constexpr int MS_PER_HOUR = 3600 * 1000;
35 static constexpr int MS_PER_DAY = 86400000;
36 static constexpr int DAY_PER_WEEK = 7;
37 static constexpr int DATE_LENGTH = 9;
38 static constexpr int DATE_STRING_LENGTH = 15;
39 static constexpr int DATE_CSTRING_LENGTH = 36;
40 static constexpr int ISO_STRING_LENGTH = 25;
41 static constexpr int TO_STRING_LENGTH = 36;
42 static constexpr int TIME_STRING_LENGTH = 18;
43 static constexpr int UTC_STRING_LENGTH = 29;
44 // the index in the Date Fields
45 static constexpr uint8_t YEAR = 0;
46 static constexpr uint8_t MONTH = 1;
47 static constexpr uint8_t DAYS = 2;
48 static constexpr uint8_t HOUR = 3;
49 static constexpr uint8_t MIN = 4;
50 static constexpr uint8_t SEC = 5;
51 static constexpr uint8_t MS = 6;
52 static constexpr uint8_t WEEKDAY = 7;
53 static constexpr uint8_t TIMEZONE = 8;
54 static constexpr int CHINA_BEFORE_1901_MIN = 485;
55 static constexpr int CHINA_AFTER_1901_MIN = 480;
56 static constexpr int CHINA_BEFORE_1901_MS = 343000;
57 static constexpr std::array<int, 3> LEAP_NUMBER = {4, 100, 400};
58 static constexpr std::array<int, 4> YEAR_NUMBER = {1970, 1969, 1901, 1601};
59 static constexpr int DAYS_1970_TO_0000 = 719468;
60 static constexpr int DAYS_IN_4_YEARS = 1460;
61 static constexpr int DAYS_IN_100_YEARS = 36524;
62 static constexpr int DAYS_IN_400_YEARS = 146097;
63 static constexpr int DAYS_MAR_TO_DEC = 306;
64 static constexpr int DAYS_JAN_AND_FEB = 59;
65 static constexpr int MONTH_COEFFICIENT = 2;
66 static constexpr int MOUTH_PER_YEAR = 12;
67 static constexpr std::array<int, 2> COEFFICIENT_TO_CIVIL = {5, 153};
68 static constexpr std::array<int, 3> MONTH_TRANSFORM = {3, 10, -9};
69 static constexpr int DAYS_FEBRUARY = 28;
70 static constexpr char DEL = 127;
71 
72 class DateUtils {
73 public:
74     explicit DateUtils() = default;
75     virtual ~DateUtils() = default;
76 
77     void TransferTimeToDate(int64_t timeMs, std::array<int64_t, DATE_LENGTH> *date);
78     // return the year, update days.
79     void GetYearFromDays(std::array<int64_t, DATE_LENGTH> *date);
80     static int64_t Mod(int64_t a, int b);
81     static bool IsLeap(int64_t year);
82     static int64_t GetDaysInYear(int64_t year);
83     static int64_t GetDaysFromYear(int64_t year);
84     static int64_t FloorDiv(int64_t a, int64_t b);
85 
86 private:
87     bool isCached_ {false};
88     int preSumDays_ {0};
89     int preDays_ {0};
90     int preMonth_ {0};
91     int preYear_ {0};
92 };
93 class JSDate : public JSObject {
94 public:
95     CAST_CHECK(JSDate, IsDate);
96 
97     static constexpr size_t TIME_VALUE_OFFSET = JSObject::SIZE;
98     ACCESSORS(TimeValue, TIME_VALUE_OFFSET, LOCAL_TIME_OFFSET)
99     ACCESSORS(LocalOffset, LOCAL_TIME_OFFSET, SIZE)  // localoffset in min
100 
101     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, TIME_VALUE_OFFSET, SIZE)
102 
103     static double MakeDay(double year, double month, double date);
104     static double MakeTime(double hour, double min, double sec, double ms);
105     static double MakeDate(double day, double time);
106     static double TimeClip(double time);
107     static JSTaggedValue LocalParseStringToMs(const CString &str);
108     static JSTaggedValue UtcParseStringToMs(const CString &str);
109     static JSTaggedValue IsoParseStringToMs(const CString &str);
110     static int GetSignedNumFromString(const CString &str, int len, int *index);
111     static bool GetNumFromString(const CString &str, int len, int *index, int *num);
112 
113     // 20.4.1.7
114     int64_t GetLocalOffsetInMin(const JSThread *thread, int64_t timeMs, bool isLocal);
115 
116     // 20.4.1.8
117     double LocalTime(double timeMs) const;
118 
119     // 20.4.1.9
120     double UTCTime(double timeMs) const;
121 
122     // 20.4.3.1
123     static JSTaggedValue Now();
124 
125     // 20.4.3.2
126     static JSTaggedValue Parse(EcmaRuntimeCallInfo *argv);
127 
128     // 20.4.3.4
129     static JSTaggedValue UTC(EcmaRuntimeCallInfo *argv);
130 
131     // 20.4.4.10
132     JSTaggedValue GetTime() const;
133 
134     // 20.4.4.19
135     JSTaggedValue GetUTCSeconds();
136 
137     // 20.4.4.35
138     JSTaggedValue ToDateString(JSThread *thread) const;
139     static CString ToDateString(JSThread *thread, double timeMs);
140 
141     // 20.4.4.36
142     JSTaggedValue ToISOString(JSThread *thread) const;
143 
144     // 20.4.4.41
145     JSTaggedValue ToString(JSThread *thread) const;
146 
147     // 20.4.4.42
148     JSTaggedValue ToTimeString(JSThread *thread) const;
149 
150     // 20.4.4.43
151     JSTaggedValue ToUTCString(JSThread *thread) const;
152 
153     // 20.4.4.44
154     JSTaggedValue ValueOf() const;
155 
156     JSTaggedValue SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, bool isLocal) const;
157     double GetDateValue(JSThread *thread, double timeMs, uint8_t code, bool isLocal) const;
158     static JSTaggedValue GetTimeFromString(const char *str, int len);
159 
160     static constexpr double MAX_DOUBLE = std::numeric_limits<double>::max();
161     static constexpr double MAX_INT = std::numeric_limits<int>::max();
162     static constexpr uint16_t NINETEEN_HUNDRED_YEAR = 1900;
163     static constexpr uint16_t THOUSAND = 1000;
164     static constexpr uint16_t HUNDRED = 100;
165     static constexpr int TEN = 10;
166     static constexpr int NUM_NINE = 9;
167     static constexpr int MONTH_PER_YEAR = 12;
168     static constexpr int MAX_DAYS_MONTH = 31;
169     static double SetDateValues(const std::array<int64_t, DATE_LENGTH> *date, bool isLocal);
170     static double SetDateValues(int64_t year, int64_t month, int64_t day);
171     static void GetDateValues(JSThread *thread, double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal);
172     static CString StrToTargetLength(const CString &str, int length);
173     static void AppendStrToTargetLength(const CString &str, int length, CString &target);
174     DECL_DUMP()
175 
176 private:
177     bool GetThisDateValues(JSThread *thread, std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const;
178     CString GetLocaleTimeStr(const std::array<int64_t, DATE_LENGTH> &fields) const;
179     CString GetLocaleDateStr(const std::array<int64_t, DATE_LENGTH> &fields) const;
180     static int64_t MathMod(int64_t a, int b);
181     template<class T>
ConvertAndAppend(T number,int length,CString & str)182     inline static void ConvertAndAppend(T number, int length, CString& str)
183     {
184         const CString cStr = ToCString(number);
185         AppendStrToTargetLength(cStr, length, str);
186     }
187 
188     static constexpr int MINUTE_PER_HOUR = 60;
189     static constexpr std::array<int, 12> MONTH_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
190     // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon)
191     static constexpr int  DAYS_FROM_MONTH [2][13] = {
192         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
193         {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
194     };
195     static constexpr int STR_LENGTH_YEAR = 4;
196     static constexpr int STR_LENGTH_OTHERS = 2;
197     static constexpr int YEAR_DELTA = 399999;
198     static constexpr int LINE_YEAR = 1970;
199     static constexpr int CENTURY = 100;
200     static constexpr char NEG = '-';
201     static constexpr char PLUS = '+';
202     static constexpr char SPACE = ' ';
203     static constexpr char COLON = ':';
204     static constexpr char POINT = '.';
205     static constexpr std::string_view NEG_STR = "-";
206     static constexpr std::string_view COMMA_STR = ",";
207     static constexpr std::string_view SPACE_STR = " ";
208     static constexpr int LENGTH_MONTH_NAME = 3;
209     static constexpr int MS_PER_MINUTE = 60000;
210     static constexpr int64_t MAX_TIME_IN_MS = static_cast<int64_t>(864000000) * 10000000;
211     static constexpr char FLAG_TIME = 'T';
212     static constexpr char FLAG_UTC = 'Z';
213     static constexpr char VIRGULE = '/';
214     static constexpr char COMMA = ',';
215     static constexpr int LENGTH_PER_TIME = 3;
216     static constexpr int MIN_LENGTH = 10;
217     static constexpr int INDEX_PLUS_NEG = 6;
218     static constexpr int ORIGIN_YEAR = 1901;
219     static constexpr uint32_t CODE_FLAG = 0x0FULL;
220     static constexpr size_t CODE_4_BIT = 4;
221 };
222 }  // namespace panda::ecmascript
223 
224 #endif  // ECMASCRIPT_JSDATE_H
225