1 // Copyright 2014 The PDFium Authors
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
9 #include "build/build_config.h"
10 #include "core/fxcrt/fx_extension.h"
11 #include "core/fxcrt/fx_system.h"
12 #include "third_party/base/check.h"
13 #include "third_party/base/containers/span.h"
14
15 namespace {
16
17 constexpr uint8_t kDaysPerMonth[12] = {31, 28, 31, 30, 31, 30,
18 31, 31, 30, 31, 30, 31};
19 constexpr uint8_t kDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30,
20 31, 31, 30, 31, 30, 31};
21 constexpr int32_t kDaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151,
22 181, 212, 243, 273, 304, 334};
23 constexpr int32_t kDaysBeforeLeapMonth[12] = {0, 31, 60, 91, 121, 152,
24 182, 213, 244, 274, 305, 335};
25 constexpr int32_t kDaysPerYear = 365;
26 constexpr int32_t kDaysPerLeapYear = 366;
27
DaysBeforeMonthInYear(int32_t iYear,uint8_t iMonth)28 int32_t DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) {
29 DCHECK(iYear != 0);
30 pdfium::span<const int32_t> p = FX_IsLeapYear(iYear)
31 ? pdfium::make_span(kDaysBeforeLeapMonth)
32 : pdfium::make_span(kDaysBeforeMonth);
33 // Note: iMonth is one-based.
34 return p[iMonth - 1];
35 }
36
DaysInYear(int32_t iYear)37 int32_t DaysInYear(int32_t iYear) {
38 DCHECK(iYear != 0);
39 return FX_IsLeapYear(iYear) ? kDaysPerLeapYear : kDaysPerYear;
40 }
41
DateToDays(int32_t iYear,uint8_t iMonth,uint8_t iDay,bool bIncludeThisDay)42 int64_t DateToDays(int32_t iYear,
43 uint8_t iMonth,
44 uint8_t iDay,
45 bool bIncludeThisDay) {
46 DCHECK(iYear != 0);
47 DCHECK(iMonth >= 1);
48 DCHECK(iMonth <= 12);
49 DCHECK(iDay >= 1);
50 DCHECK(iDay <= FX_DaysInMonth(iYear, iMonth));
51
52 int64_t iDays = DaysBeforeMonthInYear(iYear, iMonth);
53 iDays += iDay;
54 if (!bIncludeThisDay)
55 iDays--;
56
57 if (iYear > 0) {
58 iYear--;
59 } else {
60 iDays -= DaysInYear(iYear);
61 iYear++;
62 }
63 return iDays + static_cast<int64_t>(iYear) * 365 + iYear / 4 - iYear / 100 +
64 iYear / 400;
65 }
66
67 } // namespace
68
FX_DaysInMonth(int32_t iYear,uint8_t iMonth)69 uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) {
70 DCHECK(iYear != 0);
71 pdfium::span<const uint8_t> p = FX_IsLeapYear(iYear)
72 ? pdfium::make_span(kDaysPerLeapMonth)
73 : pdfium::make_span(kDaysPerMonth);
74 // Note: iMonth is one-based.
75 return p[iMonth - 1];
76 }
77
FX_IsLeapYear(int32_t iYear)78 bool FX_IsLeapYear(int32_t iYear) {
79 DCHECK(iYear != 0);
80 return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0;
81 }
82
83 // static
Now()84 CFX_DateTime CFX_DateTime::Now() {
85 time_t t = FXSYS_time(nullptr);
86 struct tm* pTime = FXSYS_localtime(&t);
87 return CFX_DateTime(
88 pTime->tm_year + 1900, static_cast<uint8_t>(pTime->tm_mon + 1),
89 static_cast<uint8_t>(pTime->tm_mday),
90 static_cast<uint8_t>(pTime->tm_hour), static_cast<uint8_t>(pTime->tm_min),
91 static_cast<uint8_t>(pTime->tm_sec), 0);
92 }
93
GetDayOfWeek() const94 int32_t CFX_DateTime::GetDayOfWeek() const {
95 int32_t v = static_cast<int32_t>(DateToDays(year_, month_, day_, true) % 7);
96 if (v < 0)
97 v += 7;
98 return v;
99 }
100
operator ==(const CFX_DateTime & other) const101 bool CFX_DateTime::operator==(const CFX_DateTime& other) const {
102 return year_ == other.year_ && month_ == other.month_ && day_ == other.day_ &&
103 hour_ == other.hour_ && minute_ == other.minute_ &&
104 second_ == other.second_ && millisecond_ == other.millisecond_;
105 }
106