• 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_ext.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 CFX_ByteString & dtStr)66 CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_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 CFX_ByteString & dtStr)131 CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString(
132     const CFX_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   FX_CHAR ch;
147   while (i < strLength && j < 4) {
148     ch = dtStr[i];
149     k = k * 10 + FXSYS_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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_toDecimalDigit(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 CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() {
267   CFX_ByteString str1;
268   str1.Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month, m_day, m_hour,
269               m_minute, m_second);
270   if (m_tzHour < 0)
271     str1 += "-";
272   else
273     str1 += "+";
274   CFX_ByteString str2;
275   str2.Format("%02d:%02u", std::abs(static_cast<int>(m_tzHour)), m_tzMinute);
276   return str1 + str2;
277 }
278 
ToPDFDateTimeString()279 CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() {
280   CFX_ByteString dtStr;
281   char tempStr[32];
282   memset(tempStr, 0, sizeof(tempStr));
283   FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u",
284                  m_year, m_month, m_day, m_hour, m_minute, m_second);
285   dtStr = CFX_ByteString(tempStr);
286   if (m_tzHour < 0)
287     dtStr += CFX_ByteString("-");
288   else
289     dtStr += CFX_ByteString("+");
290   memset(tempStr, 0, sizeof(tempStr));
291   FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'",
292                  std::abs(static_cast<int>(m_tzHour)), m_tzMinute);
293   dtStr += CFX_ByteString(tempStr);
294   return dtStr;
295 }
296 
ToSystemTime(FX_SYSTEMTIME & st)297 void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) {
298   time_t t = this->ToTime_t();
299   struct tm* pTime = localtime(&t);
300 
301   if (!pTime)
302     return;
303 
304   st.wYear = static_cast<uint16_t>(pTime->tm_year) + 1900;
305   st.wMonth = static_cast<uint16_t>(pTime->tm_mon) + 1;
306   st.wDay = static_cast<uint16_t>(pTime->tm_mday);
307   st.wDayOfWeek = static_cast<uint16_t>(pTime->tm_wday);
308   st.wHour = static_cast<uint16_t>(pTime->tm_hour);
309   st.wMinute = static_cast<uint16_t>(pTime->tm_min);
310   st.wSecond = static_cast<uint16_t>(pTime->tm_sec);
311   st.wMilliseconds = 0;
312 }
313 
ToGMT() const314 CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() const {
315   CPDFSDK_DateTime new_dt = *this;
316   new_dt.AddSeconds(-GetTimeZoneInSeconds(new_dt.m_tzHour, new_dt.m_tzMinute));
317   new_dt.m_tzHour = 0;
318   new_dt.m_tzMinute = 0;
319   return new_dt;
320 }
321 
AddDays(short days)322 CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) {
323   if (days == 0)
324     return *this;
325 
326   int16_t y = m_year;
327   uint8_t m = m_month;
328   uint8_t d = m_day;
329 
330   int ldays = days;
331   if (ldays > 0) {
332     int16_t yy = y;
333     if ((static_cast<uint16_t>(m) * 100 + d) > 300)
334       yy++;
335     int ydays = GetYearDays(yy);
336     int mdays;
337     while (ldays >= ydays) {
338       y++;
339       ldays -= ydays;
340       yy++;
341       mdays = GetMonthDays(y, m);
342       if (d > mdays) {
343         m++;
344         d -= mdays;
345       }
346       ydays = GetYearDays(yy);
347     }
348     mdays = GetMonthDays(y, m) - d + 1;
349     while (ldays >= mdays) {
350       ldays -= mdays;
351       m++;
352       d = 1;
353       mdays = GetMonthDays(y, m);
354     }
355     d += ldays;
356   } else {
357     ldays *= -1;
358     int16_t yy = y;
359     if ((static_cast<uint16_t>(m) * 100 + d) < 300)
360       yy--;
361     int ydays = GetYearDays(yy);
362     while (ldays >= ydays) {
363       y--;
364       ldays -= ydays;
365       yy--;
366       int mdays = GetMonthDays(y, m);
367       if (d > mdays) {
368         m++;
369         d -= mdays;
370       }
371       ydays = GetYearDays(yy);
372     }
373     while (ldays >= d) {
374       ldays -= d;
375       m--;
376       d = GetMonthDays(y, m);
377     }
378     d -= ldays;
379   }
380 
381   m_year = y;
382   m_month = m;
383   m_day = d;
384 
385   return *this;
386 }
387 
AddSeconds(int seconds)388 CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) {
389   if (seconds == 0)
390     return *this;
391 
392   int n;
393   int days;
394 
395   n = m_hour * 3600 + m_minute * 60 + m_second + seconds;
396   if (n < 0) {
397     days = (n - 86399) / 86400;
398     n -= days * 86400;
399   } else {
400     days = n / 86400;
401     n %= 86400;
402   }
403   m_hour = static_cast<uint8_t>(n / 3600);
404   m_hour %= 24;
405   n %= 3600;
406   m_minute = static_cast<uint8_t>(n / 60);
407   m_second = static_cast<uint8_t>(n % 60);
408   if (days != 0)
409     AddDays(days);
410 
411   return *this;
412 }
413