Home | History | Annotate | Download | only in fxcrt
      1 // 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 "core/fxcrt/cfx_datetime.h"
      8 #include "core/fxcrt/fx_system.h"
      9 
     10 #if _FX_OS_ == _FX_OS_LINUX_ || _FX_OS_ == _FX_OS_ANDROID_ || \
     11     _FX_OS_ == _FX_OS_MACOSX_
     12 #include <sys/time.h>
     13 #include <time.h>
     14 #endif
     15 
     16 namespace {
     17 
     18 const uint8_t g_FXDaysPerMonth[12] = {31, 28, 31, 30, 31, 30,
     19                                       31, 31, 30, 31, 30, 31};
     20 const uint8_t g_FXDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30,
     21                                           31, 31, 30, 31, 30, 31};
     22 const int32_t g_FXDaysBeforeMonth[12] = {0,   31,  59,  90,  120, 151,
     23                                          181, 212, 243, 273, 304, 334};
     24 const int32_t g_FXDaysBeforeLeapMonth[12] = {0,   31,  60,  91,  121, 152,
     25                                              182, 213, 244, 274, 305, 335};
     26 const int32_t g_FXDaysPerYear = 365;
     27 const int32_t g_FXDaysPerLeapYear = 366;
     28 
     29 int32_t DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) {
     30   ASSERT(iYear != 0);
     31   ASSERT(iMonth >= 1 && iMonth <= 12);
     32 
     33   const int32_t* p =
     34       FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth;
     35   return p[iMonth - 1];
     36 }
     37 
     38 int32_t DaysInYear(int32_t iYear) {
     39   ASSERT(iYear != 0);
     40   return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear;
     41 }
     42 
     43 int64_t DateToDays(int32_t iYear,
     44                    uint8_t iMonth,
     45                    uint8_t iDay,
     46                    bool bIncludeThisDay) {
     47   ASSERT(iYear != 0);
     48   ASSERT(iMonth >= 1 && iMonth <= 12);
     49   ASSERT(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth));
     50 
     51   int64_t iDays = DaysBeforeMonthInYear(iYear, iMonth);
     52   iDays += iDay;
     53   if (!bIncludeThisDay)
     54     iDays--;
     55 
     56   if (iYear > 0) {
     57     iYear--;
     58   } else {
     59     iDays -= DaysInYear(iYear);
     60     iYear++;
     61   }
     62   return iDays + static_cast<int64_t>(iYear) * 365 + iYear / 4 - iYear / 100 +
     63          iYear / 400;
     64 }
     65 
     66 struct FXUT_SYSTEMTIME {
     67   uint16_t wYear;
     68   uint16_t wMonth;
     69   uint16_t wDayOfWeek;
     70   uint16_t wDay;
     71   uint16_t wHour;
     72   uint16_t wMinute;
     73   uint16_t wSecond;
     74   uint16_t wMillisecond;
     75 };
     76 
     77 }  // namespace
     78 
     79 uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) {
     80   ASSERT(iYear != 0);
     81   ASSERT(iMonth >= 1 && iMonth <= 12);
     82 
     83   const uint8_t* p =
     84       FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth;
     85   return p[iMonth - 1];
     86 }
     87 
     88 bool FX_IsLeapYear(int32_t iYear) {
     89   ASSERT(iYear != 0);
     90   return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0;
     91 }
     92 
     93 // static
     94 CFX_DateTime CFX_DateTime::Now() {
     95   FXUT_SYSTEMTIME utLocal;
     96 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     97   ::GetLocalTime((LPSYSTEMTIME)&utLocal);
     98 #else   // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     99   timeval curTime;
    100   gettimeofday(&curTime, nullptr);
    101 
    102   struct tm st;
    103   localtime_r(&curTime.tv_sec, &st);
    104   utLocal.wYear = st.tm_year + 1900;
    105   utLocal.wMonth = st.tm_mon + 1;
    106   utLocal.wDayOfWeek = st.tm_wday;
    107   utLocal.wDay = st.tm_mday;
    108   utLocal.wHour = st.tm_hour;
    109   utLocal.wMinute = st.tm_min;
    110   utLocal.wSecond = st.tm_sec;
    111   utLocal.wMillisecond = curTime.tv_usec / 1000;
    112 #endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
    113 
    114   return CFX_DateTime(utLocal.wYear, static_cast<uint8_t>(utLocal.wMonth),
    115                       static_cast<uint8_t>(utLocal.wDay),
    116                       static_cast<uint8_t>(utLocal.wHour),
    117                       static_cast<uint8_t>(utLocal.wMinute),
    118                       static_cast<uint8_t>(utLocal.wSecond),
    119                       static_cast<uint16_t>(utLocal.wMillisecond));
    120 }
    121 
    122 int32_t CFX_DateTime::GetDayOfWeek() const {
    123   int32_t v = static_cast<int32_t>(DateToDays(year_, month_, day_, true) % 7);
    124   if (v < 0)
    125     v += 7;
    126   return v;
    127 }
    128 
    129 bool CFX_DateTime::operator==(const CFX_DateTime& other) const {
    130   return year_ == other.year_ && month_ == other.month_ && day_ == other.day_ &&
    131          hour_ == other.hour_ && minute_ == other.minute_ &&
    132          second_ == other.second_ && millisecond_ == other.millisecond_;
    133 }
    134