OLD | NEW |
(Empty) | |
| 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/include/cpdfsdk_datetime.h" |
| 8 |
| 9 #include "core/fxcrt/include/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 |
| 69 FromPDFDateTimeString(dtStr); |
| 70 } |
| 71 |
| 72 CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime) { |
| 73 FXSYS_memcpy(&dt, &datetime.dt, sizeof(FX_DATETIME)); |
| 74 } |
| 75 |
| 76 CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) { |
| 77 tzset(); |
| 78 |
| 79 dt.year = static_cast<int16_t>(st.wYear); |
| 80 dt.month = static_cast<uint8_t>(st.wMonth); |
| 81 dt.day = static_cast<uint8_t>(st.wDay); |
| 82 dt.hour = static_cast<uint8_t>(st.wHour); |
| 83 dt.minute = static_cast<uint8_t>(st.wMinute); |
| 84 dt.second = static_cast<uint8_t>(st.wSecond); |
| 85 } |
| 86 |
| 87 void CPDFSDK_DateTime::ResetDateTime() { |
| 88 tzset(); |
| 89 |
| 90 time_t curTime; |
| 91 time(&curTime); |
| 92 struct tm* newtime = localtime(&curTime); |
| 93 |
| 94 dt.year = newtime->tm_year + 1900; |
| 95 dt.month = newtime->tm_mon + 1; |
| 96 dt.day = newtime->tm_mday; |
| 97 dt.hour = newtime->tm_hour; |
| 98 dt.minute = newtime->tm_min; |
| 99 dt.second = newtime->tm_sec; |
| 100 } |
| 101 |
| 102 bool CPDFSDK_DateTime::operator==(const CPDFSDK_DateTime& datetime) const { |
| 103 return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) == 0); |
| 104 } |
| 105 |
| 106 bool CPDFSDK_DateTime::operator!=(const CPDFSDK_DateTime& datetime) const { |
| 107 return !(*this == datetime); |
| 108 } |
| 109 |
| 110 time_t CPDFSDK_DateTime::ToTime_t() const { |
| 111 struct tm newtime; |
| 112 |
| 113 newtime.tm_year = dt.year - 1900; |
| 114 newtime.tm_mon = dt.month - 1; |
| 115 newtime.tm_mday = dt.day; |
| 116 newtime.tm_hour = dt.hour; |
| 117 newtime.tm_min = dt.minute; |
| 118 newtime.tm_sec = dt.second; |
| 119 |
| 120 return mktime(&newtime); |
| 121 } |
| 122 |
| 123 CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( |
| 124 const CFX_ByteString& dtStr) { |
| 125 int strLength = dtStr.GetLength(); |
| 126 if (strLength <= 0) |
| 127 return *this; |
| 128 |
| 129 int i = 0; |
| 130 while (i < strLength && !std::isdigit(dtStr[i])) |
| 131 ++i; |
| 132 |
| 133 if (i >= strLength) |
| 134 return *this; |
| 135 |
| 136 int j = 0; |
| 137 int k = 0; |
| 138 FX_CHAR ch; |
| 139 while (i < strLength && j < 4) { |
| 140 ch = dtStr[i]; |
| 141 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 142 j++; |
| 143 if (!std::isdigit(ch)) |
| 144 break; |
| 145 i++; |
| 146 } |
| 147 dt.year = static_cast<int16_t>(k); |
| 148 if (i >= strLength || j < 4) |
| 149 return *this; |
| 150 |
| 151 j = 0; |
| 152 k = 0; |
| 153 while (i < strLength && j < 2) { |
| 154 ch = dtStr[i]; |
| 155 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 156 j++; |
| 157 if (!std::isdigit(ch)) |
| 158 break; |
| 159 i++; |
| 160 } |
| 161 dt.month = static_cast<uint8_t>(k); |
| 162 if (i >= strLength || j < 2) |
| 163 return *this; |
| 164 |
| 165 j = 0; |
| 166 k = 0; |
| 167 while (i < strLength && j < 2) { |
| 168 ch = dtStr[i]; |
| 169 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 170 j++; |
| 171 if (!std::isdigit(ch)) |
| 172 break; |
| 173 i++; |
| 174 } |
| 175 dt.day = static_cast<uint8_t>(k); |
| 176 if (i >= strLength || j < 2) |
| 177 return *this; |
| 178 |
| 179 j = 0; |
| 180 k = 0; |
| 181 while (i < strLength && j < 2) { |
| 182 ch = dtStr[i]; |
| 183 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 184 j++; |
| 185 if (!std::isdigit(ch)) |
| 186 break; |
| 187 i++; |
| 188 } |
| 189 dt.hour = static_cast<uint8_t>(k); |
| 190 if (i >= strLength || j < 2) |
| 191 return *this; |
| 192 |
| 193 j = 0; |
| 194 k = 0; |
| 195 while (i < strLength && j < 2) { |
| 196 ch = dtStr[i]; |
| 197 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 198 j++; |
| 199 if (!std::isdigit(ch)) |
| 200 break; |
| 201 i++; |
| 202 } |
| 203 dt.minute = static_cast<uint8_t>(k); |
| 204 if (i >= strLength || j < 2) |
| 205 return *this; |
| 206 |
| 207 j = 0; |
| 208 k = 0; |
| 209 while (i < strLength && j < 2) { |
| 210 ch = dtStr[i]; |
| 211 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 212 j++; |
| 213 if (!std::isdigit(ch)) |
| 214 break; |
| 215 i++; |
| 216 } |
| 217 dt.second = static_cast<uint8_t>(k); |
| 218 if (i >= strLength || j < 2) |
| 219 return *this; |
| 220 |
| 221 ch = dtStr[i++]; |
| 222 if (ch != '-' && ch != '+') |
| 223 return *this; |
| 224 if (ch == '-') |
| 225 dt.tzHour = -1; |
| 226 else |
| 227 dt.tzHour = 1; |
| 228 j = 0; |
| 229 k = 0; |
| 230 while (i < strLength && j < 2) { |
| 231 ch = dtStr[i]; |
| 232 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 233 j++; |
| 234 if (!std::isdigit(ch)) |
| 235 break; |
| 236 i++; |
| 237 } |
| 238 dt.tzHour *= static_cast<int8_t>(k); |
| 239 if (i >= strLength || j < 2) |
| 240 return *this; |
| 241 |
| 242 if (dtStr[i++] != '\'') |
| 243 return *this; |
| 244 j = 0; |
| 245 k = 0; |
| 246 while (i < strLength && j < 2) { |
| 247 ch = dtStr[i]; |
| 248 k = k * 10 + FXSYS_toDecimalDigit(ch); |
| 249 j++; |
| 250 if (!std::isdigit(ch)) |
| 251 break; |
| 252 i++; |
| 253 } |
| 254 dt.tzMinute = static_cast<uint8_t>(k); |
| 255 return *this; |
| 256 } |
| 257 |
| 258 CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() { |
| 259 CFX_ByteString str1; |
| 260 str1.Format("%04d-%02u-%02u %02u:%02u:%02u ", dt.year, dt.month, dt.day, |
| 261 dt.hour, dt.minute, dt.second); |
| 262 if (dt.tzHour < 0) |
| 263 str1 += "-"; |
| 264 else |
| 265 str1 += "+"; |
| 266 CFX_ByteString str2; |
| 267 str2.Format("%02d:%02u", std::abs(static_cast<int>(dt.tzHour)), dt.tzMinute); |
| 268 return str1 + str2; |
| 269 } |
| 270 |
| 271 CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() { |
| 272 CFX_ByteString dtStr; |
| 273 char tempStr[32]; |
| 274 memset(tempStr, 0, sizeof(tempStr)); |
| 275 FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u", |
| 276 dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); |
| 277 dtStr = CFX_ByteString(tempStr); |
| 278 if (dt.tzHour < 0) |
| 279 dtStr += CFX_ByteString("-"); |
| 280 else |
| 281 dtStr += CFX_ByteString("+"); |
| 282 memset(tempStr, 0, sizeof(tempStr)); |
| 283 FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'", |
| 284 std::abs(static_cast<int>(dt.tzHour)), dt.tzMinute); |
| 285 dtStr += CFX_ByteString(tempStr); |
| 286 return dtStr; |
| 287 } |
| 288 |
| 289 void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) { |
| 290 time_t t = this->ToTime_t(); |
| 291 struct tm* pTime = localtime(&t); |
| 292 |
| 293 if (!pTime) |
| 294 return; |
| 295 |
| 296 st.wYear = static_cast<uint16_t>(pTime->tm_year) + 1900; |
| 297 st.wMonth = static_cast<uint16_t>(pTime->tm_mon) + 1; |
| 298 st.wDay = static_cast<uint16_t>(pTime->tm_mday); |
| 299 st.wDayOfWeek = static_cast<uint16_t>(pTime->tm_wday); |
| 300 st.wHour = static_cast<uint16_t>(pTime->tm_hour); |
| 301 st.wMinute = static_cast<uint16_t>(pTime->tm_min); |
| 302 st.wSecond = static_cast<uint16_t>(pTime->tm_sec); |
| 303 st.wMilliseconds = 0; |
| 304 } |
| 305 |
| 306 CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() const { |
| 307 CPDFSDK_DateTime new_dt = *this; |
| 308 new_dt.AddSeconds( |
| 309 -GetTimeZoneInSeconds(new_dt.dt.tzHour, new_dt.dt.tzMinute)); |
| 310 new_dt.dt.tzHour = 0; |
| 311 new_dt.dt.tzMinute = 0; |
| 312 return new_dt; |
| 313 } |
| 314 |
| 315 CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) { |
| 316 if (days == 0) |
| 317 return *this; |
| 318 |
| 319 int16_t y = dt.year; |
| 320 uint8_t m = dt.month; |
| 321 uint8_t d = dt.day; |
| 322 |
| 323 int ldays = days; |
| 324 if (ldays > 0) { |
| 325 int16_t yy = y; |
| 326 if ((static_cast<uint16_t>(m) * 100 + d) > 300) |
| 327 yy++; |
| 328 int ydays = GetYearDays(yy); |
| 329 int mdays; |
| 330 while (ldays >= ydays) { |
| 331 y++; |
| 332 ldays -= ydays; |
| 333 yy++; |
| 334 mdays = GetMonthDays(y, m); |
| 335 if (d > mdays) { |
| 336 m++; |
| 337 d -= mdays; |
| 338 } |
| 339 ydays = GetYearDays(yy); |
| 340 } |
| 341 mdays = GetMonthDays(y, m) - d + 1; |
| 342 while (ldays >= mdays) { |
| 343 ldays -= mdays; |
| 344 m++; |
| 345 d = 1; |
| 346 mdays = GetMonthDays(y, m); |
| 347 } |
| 348 d += ldays; |
| 349 } else { |
| 350 ldays *= -1; |
| 351 int16_t yy = y; |
| 352 if ((static_cast<uint16_t>(m) * 100 + d) < 300) |
| 353 yy--; |
| 354 int ydays = GetYearDays(yy); |
| 355 while (ldays >= ydays) { |
| 356 y--; |
| 357 ldays -= ydays; |
| 358 yy--; |
| 359 int mdays = GetMonthDays(y, m); |
| 360 if (d > mdays) { |
| 361 m++; |
| 362 d -= mdays; |
| 363 } |
| 364 ydays = GetYearDays(yy); |
| 365 } |
| 366 while (ldays >= d) { |
| 367 ldays -= d; |
| 368 m--; |
| 369 d = GetMonthDays(y, m); |
| 370 } |
| 371 d -= ldays; |
| 372 } |
| 373 |
| 374 dt.year = y; |
| 375 dt.month = m; |
| 376 dt.day = d; |
| 377 |
| 378 return *this; |
| 379 } |
| 380 |
| 381 CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) { |
| 382 if (seconds == 0) |
| 383 return *this; |
| 384 |
| 385 int n; |
| 386 int days; |
| 387 |
| 388 n = dt.hour * 3600 + dt.minute * 60 + dt.second + seconds; |
| 389 if (n < 0) { |
| 390 days = (n - 86399) / 86400; |
| 391 n -= days * 86400; |
| 392 } else { |
| 393 days = n / 86400; |
| 394 n %= 86400; |
| 395 } |
| 396 dt.hour = static_cast<uint8_t>(n / 3600); |
| 397 dt.hour %= 24; |
| 398 n %= 3600; |
| 399 dt.minute = static_cast<uint8_t>(n / 60); |
| 400 dt.second = static_cast<uint8_t>(n % 60); |
| 401 if (days != 0) |
| 402 AddDays(days); |
| 403 |
| 404 return *this; |
| 405 } |
OLD | NEW |