blob: 403a731ad697ddcff1c589d82c4c91e27071918c [file] [log] [blame]
Tom Sepez86e5fbf2018-11-01 21:21:52 +00001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "fxjs/fx_date_helpers.h"
8
9#include <time.h>
10
11#include "core/fxcrt/fx_extension.h"
12#include "core/fxcrt/fx_system.h"
13#include "fpdfsdk/cpdfsdk_helpers.h"
14
15namespace fxjs {
16namespace {
17
18constexpr uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151,
19 181, 212, 243, 273, 304, 334};
20constexpr uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152,
21 182, 213, 244, 274, 305, 335};
22
23double Mod(double x, double y) {
24 double r = fmod(x, y);
25 if (r < 0)
26 r += y;
27 return r;
28}
29
30double GetLocalTZA() {
31 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
32 return 0;
33 time_t t = 0;
34 FXSYS_time(&t);
35 FXSYS_localtime(&t);
36#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
37 // In gcc 'timezone' is a global variable declared in time.h. In VC++, that
38 // variable was removed in VC++ 2015, with _get_timezone replacing it.
39 long timezone = 0;
40 _get_timezone(&timezone);
41#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
42 return (double)(-(timezone * 1000));
43}
44
45int GetDaylightSavingTA(double d) {
46 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
47 return 0;
48 time_t t = (time_t)(d / 1000);
49 struct tm* tmp = FXSYS_localtime(&t);
50 if (!tmp)
51 return 0;
52 if (tmp->tm_isdst > 0)
53 // One hour.
54 return (int)60 * 60 * 1000;
55 return 0;
56}
57
58bool IsLeapYear(int year) {
59 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
60}
61
62int DayFromYear(int y) {
63 return (int)(365 * (y - 1970.0) + floor((y - 1969.0) / 4) -
64 floor((y - 1901.0) / 100) + floor((y - 1601.0) / 400));
65}
66
67double TimeFromYear(int y) {
68 return 86400000.0 * DayFromYear(y);
69}
70
71double TimeFromYearMonth(int y, int m) {
72 const uint16_t* pMonth = IsLeapYear(y) ? leapDaysMonth : daysMonth;
73 return TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
74}
75
76int Day(double t) {
77 return static_cast<int>(floor(t / 86400000.0));
78}
79
80int YearFromTime(double t) {
81 // estimate the time.
82 int y = 1970 + static_cast<int>(t / (365.2425 * 86400000.0));
83 if (TimeFromYear(y) <= t) {
84 while (TimeFromYear(y + 1) <= t)
85 y++;
86 } else {
87 while (TimeFromYear(y) > t)
88 y--;
89 }
90 return y;
91}
92
93int DayWithinYear(double t) {
94 int year = YearFromTime(t);
95 int day = Day(t);
96 return day - DayFromYear(year);
97}
98
99int MonthFromTime(double t) {
100 int day = DayWithinYear(t);
101 int year = YearFromTime(t);
102 if (0 <= day && day < 31)
103 return 0;
104 if (31 <= day && day < 59 + IsLeapYear(year))
105 return 1;
106 if ((59 + IsLeapYear(year)) <= day && day < (90 + IsLeapYear(year)))
107 return 2;
108 if ((90 + IsLeapYear(year)) <= day && day < (120 + IsLeapYear(year)))
109 return 3;
110 if ((120 + IsLeapYear(year)) <= day && day < (151 + IsLeapYear(year)))
111 return 4;
112 if ((151 + IsLeapYear(year)) <= day && day < (181 + IsLeapYear(year)))
113 return 5;
114 if ((181 + IsLeapYear(year)) <= day && day < (212 + IsLeapYear(year)))
115 return 6;
116 if ((212 + IsLeapYear(year)) <= day && day < (243 + IsLeapYear(year)))
117 return 7;
118 if ((243 + IsLeapYear(year)) <= day && day < (273 + IsLeapYear(year)))
119 return 8;
120 if ((273 + IsLeapYear(year)) <= day && day < (304 + IsLeapYear(year)))
121 return 9;
122 if ((304 + IsLeapYear(year)) <= day && day < (334 + IsLeapYear(year)))
123 return 10;
124 if ((334 + IsLeapYear(year)) <= day && day < (365 + IsLeapYear(year)))
125 return 11;
126
127 return -1;
128}
129
130int DateFromTime(double t) {
131 int day = DayWithinYear(t);
132 int year = YearFromTime(t);
133 int leap = IsLeapYear(year);
134 int month = MonthFromTime(t);
135 switch (month) {
136 case 0:
137 return day + 1;
138 case 1:
139 return day - 30;
140 case 2:
141 return day - 58 - leap;
142 case 3:
143 return day - 89 - leap;
144 case 4:
145 return day - 119 - leap;
146 case 5:
147 return day - 150 - leap;
148 case 6:
149 return day - 180 - leap;
150 case 7:
151 return day - 211 - leap;
152 case 8:
153 return day - 242 - leap;
154 case 9:
155 return day - 272 - leap;
156 case 10:
157 return day - 303 - leap;
158 case 11:
159 return day - 333 - leap;
160 default:
161 return 0;
162 }
163}
164
165} // namespace
166
167double FX_GetDateTime() {
168 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
169 return 0;
170
171 time_t t = FXSYS_time(nullptr);
172 struct tm* pTm = FXSYS_localtime(&t);
173 double t1 = TimeFromYear(pTm->tm_year + 1900);
174 return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
175 pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
176}
177
178int FX_GetYearFromTime(double dt) {
179 return YearFromTime(dt);
180}
181
182int FX_GetMonthFromTime(double dt) {
183 return MonthFromTime(dt);
184}
185
186int FX_GetDayFromTime(double dt) {
187 return DateFromTime(dt);
188}
189
190int FX_GetHourFromTime(double dt) {
191 return (int)Mod(floor(dt / (60 * 60 * 1000)), 24);
192}
193
194int FX_GetMinFromTime(double dt) {
195 return (int)Mod(floor(dt / (60 * 1000)), 60);
196}
197
198int FX_GetSecFromTime(double dt) {
199 return (int)Mod(floor(dt / 1000), 60);
200}
201
202double FX_LocalTime(double d) {
203 return d + GetLocalTZA() + GetDaylightSavingTA(d);
204}
205
206double FX_MakeDay(int nYear, int nMonth, int nDate) {
207 double y = static_cast<double>(nYear);
208 double m = static_cast<double>(nMonth);
209 double dt = static_cast<double>(nDate);
210 double ym = y + floor(m / 12);
211 double mn = Mod(m, 12);
212 double t = TimeFromYearMonth(static_cast<int>(ym), static_cast<int>(mn));
213 if (YearFromTime(t) != ym || MonthFromTime(t) != mn || DateFromTime(t) != 1)
214 return std::nan("");
215
216 return Day(t) + dt - 1;
217}
218
219double FX_MakeTime(int nHour, int nMin, int nSec, int nMs) {
220 double h = static_cast<double>(nHour);
221 double m = static_cast<double>(nMin);
222 double s = static_cast<double>(nSec);
223 double milli = static_cast<double>(nMs);
224 return h * 3600000 + m * 60000 + s * 1000 + milli;
225}
226
227double FX_MakeDate(double day, double time) {
228 if (!std::isfinite(day) || !std::isfinite(time))
229 return std::nan("");
230
231 return day * 86400000 + time;
232}
233
Tom Sepezd105d2e2018-11-02 16:56:37 +0000234int FX_ParseStringInteger(const WideString& str,
235 size_t nStart,
236 size_t* pSkip,
237 size_t nMaxStep) {
238 int nRet = 0;
239 size_t nSkip = 0;
240 for (size_t i = nStart; i < str.GetLength(); ++i) {
241 if (i - nStart > 10)
242 break;
243
244 wchar_t c = str[i];
245 if (!std::iswdigit(c))
246 break;
247
248 nRet = nRet * 10 + FXSYS_DecimalCharToInt(c);
249 ++nSkip;
250 if (nSkip >= nMaxStep)
251 break;
252 }
253
254 *pSkip = nSkip;
255 return nRet;
256}
257
258WideString FX_ParseStringString(const WideString& str,
259 size_t nStart,
260 size_t* pSkip) {
261 WideString swRet;
262 swRet.Reserve(str.GetLength());
263 for (size_t i = nStart; i < str.GetLength(); ++i) {
264 wchar_t c = str[i];
265 if (!std::iswalnum(c))
266 break;
267
268 swRet += c;
269 }
270
271 *pSkip = swRet.GetLength();
272 return swRet;
273}
274
Tom Sepez86e5fbf2018-11-01 21:21:52 +0000275} // namespace fxjs