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