Home | History | Annotate | Download | only in fpdfsdk
      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 
     13 int GetTimeZoneInSeconds(int8_t tzhour, uint8_t tzminute) {
     14   return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60);
     15 }
     16 
     17 bool IsLeapYear(int16_t year) {
     18   return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
     19 }
     20 
     21 uint16_t GetYearDays(int16_t year) {
     22   return (IsLeapYear(year) ? 366 : 365);
     23 }
     24 
     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 
     62 CPDFSDK_DateTime::CPDFSDK_DateTime() {
     63   ResetDateTime();
     64 }
     65 
     66 CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) {
     67   ResetDateTime();
     68   FromPDFDateTimeString(dtStr);
     69 }
     70 
     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 
     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 
     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 
    107 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 
    114 bool CPDFSDK_DateTime::operator!=(const CPDFSDK_DateTime& datetime) const {
    115   return !(*this == datetime);
    116 }
    117 
    118 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 
    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 
    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 
    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 
    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 
    314 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 
    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 
    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