• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "fpdfsdk/cpdfsdk_datetime.h"
8 
9 #include "core/fxcrt/fx_extension.h"
10 
11 namespace {
12 
GetTimeZoneInSeconds(int8_t tzhour,uint8_t tzminute)13 int GetTimeZoneInSeconds(int8_t tzhour, uint8_t tzminute) {
14   return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60);
15 }
16 
IsLeapYear(int16_t year)17 bool IsLeapYear(int16_t year) {
18   return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
19 }
20 
GetYearDays(int16_t year)21 uint16_t GetYearDays(int16_t year) {
22   return (IsLeapYear(year) ? 366 : 365);
23 }
24 
GetMonthDays(int16_t year,uint8_t month)25 uint8_t GetMonthDays(int16_t year, uint8_t month) {
26   uint8_t mDays;
27   switch (month) {
28     case 1:
29     case 3:
30     case 5:
31     case 7:
32     case 8:
33     case 10:
34     case 12:
35       mDays = 31;
36       break;
37 
38     case 4:
39     case 6:
40     case 9:
41     case 11:
42       mDays = 30;
43       break;
44 
45     case 2:
46       if (IsLeapYear(year))
47         mDays = 29;
48       else
49         mDays = 28;
50       break;
51 
52     default:
53       mDays = 0;
54       break;
55   }
56 
57   return mDays;
58 }
59 
60 }  // namespace
61 
CPDFSDK_DateTime()62 CPDFSDK_DateTime::CPDFSDK_DateTime() {
63   ResetDateTime();
64 }
65 
CPDFSDK_DateTime(const ByteString & dtStr)66 CPDFSDK_DateTime::CPDFSDK_DateTime(const ByteString& dtStr) {
67   ResetDateTime();
68   FromPDFDateTimeString(dtStr);
69 }
70 
CPDFSDK_DateTime(const CPDFSDK_DateTime & that)71 CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& that)
72     : m_year(that.m_year),
73       m_month(that.m_month),
74       m_day(that.m_day),
75       m_hour(that.m_hour),
76       m_minute(that.m_minute),
77       m_second(that.m_second),
78       m_tzHour(that.m_tzHour),
79       m_tzMinute(that.m_tzMinute) {}
80 
CPDFSDK_DateTime(const FX_SYSTEMTIME & st)81 CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) {
82   tzset();
83 
84   m_year = static_cast<int16_t>(st.wYear);
85   m_month = static_cast<uint8_t>(st.wMonth);
86   m_day = static_cast<uint8_t>(st.wDay);
87   m_hour = static_cast<uint8_t>(st.wHour);
88   m_minute = static_cast<uint8_t>(st.wMinute);
89   m_second = static_cast<uint8_t>(st.wSecond);
90 }
91 
ResetDateTime()92 void CPDFSDK_DateTime::ResetDateTime() {
93   tzset();
94 
95   time_t curTime;
96   time(&curTime);
97 
98   struct tm* newtime = localtime(&curTime);
99   m_year = newtime->tm_year + 1900;
100   m_month = newtime->tm_mon + 1;
101   m_day = newtime->tm_mday;
102   m_hour = newtime->tm_hour;
103   m_minute = newtime->tm_min;
104   m_second = newtime->tm_sec;
105 }
106 
operator ==(const CPDFSDK_DateTime & that) const107 bool CPDFSDK_DateTime::operator==(const CPDFSDK_DateTime& that) const {
108   return m_year == that.m_year && m_month == that.m_month &&
109          m_day == that.m_day && m_hour == that.m_hour &&
110          m_minute == that.m_minute && m_second == that.m_second &&
111          m_tzHour == that.m_tzHour && m_tzMinute == that.m_tzMinute;
112 }
113 
operator !=(const CPDFSDK_DateTime & datetime) const114 bool CPDFSDK_DateTime::operator!=(const CPDFSDK_DateTime& datetime) const {
115   return !(*this == datetime);
116 }
117 
ToTime_t() const118 time_t CPDFSDK_DateTime::ToTime_t() const {
119   struct tm newtime;
120 
121   newtime.tm_year = m_year - 1900;
122   newtime.tm_mon = m_month - 1;
123   newtime.tm_mday = m_day;
124   newtime.tm_hour = m_hour;
125   newtime.tm_min = m_minute;
126   newtime.tm_sec = m_second;
127 
128   return mktime(&newtime);
129 }
130 
FromPDFDateTimeString(const ByteString & dtStr)131 CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString(
132     const ByteString& dtStr) {
133   int strLength = dtStr.GetLength();
134   if (strLength <= 0)
135     return *this;
136 
137   int i = 0;
138   while (i < strLength && !std::isdigit(dtStr[i]))
139     ++i;
140 
141   if (i >= strLength)
142     return *this;
143 
144   int j = 0;
145   int k = 0;
146   char ch;
147   while (i < strLength && j < 4) {
148     ch = dtStr[i];
149     k = k * 10 + FXSYS_DecimalCharToInt(ch);
150     j++;
151     if (!std::isdigit(ch))
152       break;
153     i++;
154   }
155   m_year = static_cast<int16_t>(k);
156   if (i >= strLength || j < 4)
157     return *this;
158 
159   j = 0;
160   k = 0;
161   while (i < strLength && j < 2) {
162     ch = dtStr[i];
163     k = k * 10 + FXSYS_DecimalCharToInt(ch);
164     j++;
165     if (!std::isdigit(ch))
166       break;
167     i++;
168   }
169   m_month = static_cast<uint8_t>(k);
170   if (i >= strLength || j < 2)
171     return *this;
172 
173   j = 0;
174   k = 0;
175   while (i < strLength && j < 2) {
176     ch = dtStr[i];
177     k = k * 10 + FXSYS_DecimalCharToInt(ch);
178     j++;
179     if (!std::isdigit(ch))
180       break;
181     i++;
182   }
183   m_day = static_cast<uint8_t>(k);
184   if (i >= strLength || j < 2)
185     return *this;
186 
187   j = 0;
188   k = 0;
189   while (i < strLength && j < 2) {
190     ch = dtStr[i];
191     k = k * 10 + FXSYS_DecimalCharToInt(ch);
192     j++;
193     if (!std::isdigit(ch))
194       break;
195     i++;
196   }
197   m_hour = static_cast<uint8_t>(k);
198   if (i >= strLength || j < 2)
199     return *this;
200 
201   j = 0;
202   k = 0;
203   while (i < strLength && j < 2) {
204     ch = dtStr[i];
205     k = k * 10 + FXSYS_DecimalCharToInt(ch);
206     j++;
207     if (!std::isdigit(ch))
208       break;
209     i++;
210   }
211   m_minute = static_cast<uint8_t>(k);
212   if (i >= strLength || j < 2)
213     return *this;
214 
215   j = 0;
216   k = 0;
217   while (i < strLength && j < 2) {
218     ch = dtStr[i];
219     k = k * 10 + FXSYS_DecimalCharToInt(ch);
220     j++;
221     if (!std::isdigit(ch))
222       break;
223     i++;
224   }
225   m_second = static_cast<uint8_t>(k);
226   if (i >= strLength || j < 2)
227     return *this;
228 
229   ch = dtStr[i++];
230   if (ch != '-' && ch != '+')
231     return *this;
232   if (ch == '-')
233     m_tzHour = -1;
234   else
235     m_tzHour = 1;
236   j = 0;
237   k = 0;
238   while (i < strLength && j < 2) {
239     ch = dtStr[i];
240     k = k * 10 + FXSYS_DecimalCharToInt(ch);
241     j++;
242     if (!std::isdigit(ch))
243       break;
244     i++;
245   }
246   m_tzHour *= static_cast<int8_t>(k);
247   if (i >= strLength || j < 2)
248     return *this;
249 
250   if (dtStr[i++] != '\'')
251     return *this;
252   j = 0;
253   k = 0;
254   while (i < strLength && j < 2) {
255     ch = dtStr[i];
256     k = k * 10 + FXSYS_DecimalCharToInt(ch);
257     j++;
258     if (!std::isdigit(ch))
259       break;
260     i++;
261   }
262   m_tzMinute = static_cast<uint8_t>(k);
263   return *this;
264 }
265 
ToCommonDateTimeString()266 ByteString CPDFSDK_DateTime::ToCommonDateTimeString() {
267   return ByteString::Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month,
268                             m_day, m_hour, m_minute, m_second) +
269          (m_tzHour < 0 ? "-" : "+") +
270          ByteString::Format("%02d:%02u", std::abs(static_cast<int>(m_tzHour)),
271                             m_tzMinute);
272 }
273 
ToPDFDateTimeString()274 ByteString CPDFSDK_DateTime::ToPDFDateTimeString() {
275   ByteString dtStr;
276   char tempStr[32];
277   memset(tempStr, 0, sizeof(tempStr));
278   FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u",
279                  m_year, m_month, m_day, m_hour, m_minute, m_second);
280   dtStr = ByteString(tempStr);
281   if (m_tzHour < 0)
282     dtStr += ByteString("-");
283   else
284     dtStr += ByteString("+");
285   memset(tempStr, 0, sizeof(tempStr));
286   FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'",
287                  std::abs(static_cast<int>(m_tzHour)), m_tzMinute);
288   dtStr += ByteString(tempStr);
289   return dtStr;
290 }
291 
ToSystemTime(FX_SYSTEMTIME & st)292 void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) {
293   time_t t = this->ToTime_t();
294   struct tm* pTime = localtime(&t);
295 
296   if (!pTime)
297     return;
298 
299   st.wYear = static_cast<uint16_t>(pTime->tm_year) + 1900;
300   st.wMonth = static_cast<uint16_t>(pTime->tm_mon) + 1;
301   st.wDay = static_cast<uint16_t>(pTime->tm_mday);
302   st.wDayOfWeek = static_cast<uint16_t>(pTime->tm_wday);
303   st.wHour = static_cast<uint16_t>(pTime->tm_hour);
304   st.wMinute = static_cast<uint16_t>(pTime->tm_min);
305   st.wSecond = static_cast<uint16_t>(pTime->tm_sec);
306   st.wMilliseconds = 0;
307 }
308 
ToGMT() const309 CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() const {
310   CPDFSDK_DateTime new_dt = *this;
311   new_dt.AddSeconds(-GetTimeZoneInSeconds(new_dt.m_tzHour, new_dt.m_tzMinute));
312   new_dt.m_tzHour = 0;
313   new_dt.m_tzMinute = 0;
314   return new_dt;
315 }
316 
AddDays(short days)317 CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) {
318   if (days == 0)
319     return *this;
320 
321   int16_t y = m_year;
322   uint8_t m = m_month;
323   uint8_t d = m_day;
324 
325   int ldays = days;
326   if (ldays > 0) {
327     int16_t yy = y;
328     if ((static_cast<uint16_t>(m) * 100 + d) > 300)
329       yy++;
330     int ydays = GetYearDays(yy);
331     int mdays;
332     while (ldays >= ydays) {
333       y++;
334       ldays -= ydays;
335       yy++;
336       mdays = GetMonthDays(y, m);
337       if (d > mdays) {
338         m++;
339         d -= mdays;
340       }
341       ydays = GetYearDays(yy);
342     }
343     mdays = GetMonthDays(y, m) - d + 1;
344     while (ldays >= mdays) {
345       ldays -= mdays;
346       m++;
347       d = 1;
348       mdays = GetMonthDays(y, m);
349     }
350     d += ldays;
351   } else {
352     ldays *= -1;
353     int16_t yy = y;
354     if ((static_cast<uint16_t>(m) * 100 + d) < 300)
355       yy--;
356     int ydays = GetYearDays(yy);
357     while (ldays >= ydays) {
358       y--;
359       ldays -= ydays;
360       yy--;
361       int mdays = GetMonthDays(y, m);
362       if (d > mdays) {
363         m++;
364         d -= mdays;
365       }
366       ydays = GetYearDays(yy);
367     }
368     while (ldays >= d) {
369       ldays -= d;
370       m--;
371       d = GetMonthDays(y, m);
372     }
373     d -= ldays;
374   }
375 
376   m_year = y;
377   m_month = m;
378   m_day = d;
379 
380   return *this;
381 }
382 
AddSeconds(int seconds)383 CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) {
384   if (seconds == 0)
385     return *this;
386 
387   int n;
388   int days;
389 
390   n = m_hour * 3600 + m_minute * 60 + m_second + seconds;
391   if (n < 0) {
392     days = (n - 86399) / 86400;
393     n -= days * 86400;
394   } else {
395     days = n / 86400;
396     n %= 86400;
397   }
398   m_hour = static_cast<uint8_t>(n / 3600);
399   m_hour %= 24;
400   n %= 3600;
401   m_minute = static_cast<uint8_t>(n / 60);
402   m_second = static_cast<uint8_t>(n % 60);
403   if (days != 0)
404     AddDays(days);
405 
406   return *this;
407 }
408