| OLD | NEW |
| 1 /* | 1 /* Portions are Copyright (C) 2007 Google Inc */ |
| 2 * Portions are Copyright (C) 2007 Google Inc | 2 /* ***** BEGIN LICENSE BLOCK ***** |
| 3 * | 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 4 * ***** BEGIN LICENSE BLOCK ***** | 4 * |
| 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 5 * The contents of this file are subject to the Mozilla Public License Version |
| 6 * | 6 * 1.1 (the "License"); you may not use this file except in compliance with |
| 7 * The contents of this file are subject to the Mozilla Public License Version | 7 * the License. You may obtain a copy of the License at |
| 8 * 1.1 (the "License"); you may not use this file except in compliance with | 8 * http://www.mozilla.org/MPL/ |
| 9 * the License. You may obtain a copy of the License at | 9 * |
| 10 * http://www.mozilla.org/MPL/ | 10 * Software distributed under the License is distributed on an "AS IS" basis, |
| 11 * | 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 12 * Software distributed under the License is distributed on an "AS IS" basis, | 12 * for the specific language governing rights and limitations under the |
| 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | 13 * License. |
| 14 * for the specific language governing rights and limitations under the | 14 * |
| 15 * License. | 15 * The Original Code is the Netscape Portable Runtime (NSPR). |
| 16 * | 16 * |
| 17 * The Original Code is the Netscape Portable Runtime (NSPR). | 17 * The Initial Developer of the Original Code is |
| 18 * | 18 * Netscape Communications Corporation. |
| 19 * The Initial Developer of the Original Code is | 19 * Portions created by the Initial Developer are Copyright (C) 1998-2000 |
| 20 * Netscape Communications Corporation. | 20 * the Initial Developer. All Rights Reserved. |
| 21 * Portions created by the Initial Developer are Copyright (C) 1998-2000 | 21 * |
| 22 * the Initial Developer. All Rights Reserved. | 22 * Contributor(s): |
| 23 * | 23 * |
| 24 * Contributor(s): | 24 * Alternatively, the contents of this file may be used under the terms of |
| 25 * | 25 * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 26 * Alternatively, the contents of this file may be used under the terms of | 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 27 * either the GNU General Public License Version 2 or later (the "GPL"), or | 27 * in which case the provisions of the GPL or the LGPL are applicable instead |
| 28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | 28 * of those above. If you wish to allow use of your version of this file only |
| 29 * in which case the provisions of the GPL or the LGPL are applicable instead | 29 * under the terms of either the GPL or the LGPL, and not to allow others to |
| 30 * of those above. If you wish to allow use of your version of this file only | 30 * use your version of this file under the terms of the MPL, indicate your |
| 31 * under the terms of either the GPL or the LGPL, and not to allow others to | 31 * decision by deleting the provisions above and replace them with the notice |
| 32 * use your version of this file under the terms of the MPL, indicate your | 32 * and other provisions required by the GPL or the LGPL. If you do not delete |
| 33 * decision by deleting the provisions above and replace them with the notice | 33 * the provisions above, a recipient may use your version of this file under |
| 34 * and other provisions required by the GPL or the LGPL. If you do not delete | 34 * the terms of any one of the MPL, the GPL or the LGPL. |
| 35 * the provisions above, a recipient may use your version of this file under | 35 * |
| 36 * the terms of any one of the MPL, the GPL or the LGPL. | 36 * ***** END LICENSE BLOCK ***** */ |
| 37 * | |
| 38 * ***** END LICENSE BLOCK ***** | |
| 39 * | |
| 40 */ | |
| 41 | 37 |
| 42 /* | 38 /* |
| 43 * prtime.cc -- | 39 * prtime.cc -- |
| 44 * NOTE: The original nspr file name is prtime.c | 40 * NOTE: The original nspr file name is prtime.c |
| 45 * | 41 * |
| 46 * NSPR date and time functions | 42 * NSPR date and time functions |
| 47 * | 43 * |
| 48 * CVS revision 3.31 | 44 * CVS revision 3.36 |
| 49 */ | 45 */ |
| 50 | 46 |
| 51 /* | 47 /* |
| 52 * The following functions were copied from the NSPR prtime.c file. | 48 * The following functions were copied from the NSPR prtime.c file. |
| 53 * PR_ParseTimeString | 49 * PR_ParseTimeString |
| 54 * PR_ImplodeTime | 50 * We inlined the new PR_ParseTimeStringToExplodedTime function to avoid |
| 55 * This was modified to use the Win32 SYSTEMTIME/FILETIME structures | 51 * copying PR_ExplodeTime and PR_LocalTimeParameters. (The PR_ExplodeTime |
| 56 * and the timezone offsets are applied to the FILETIME structure. | 52 * and PR_ImplodeTime calls cancel each other out.) |
| 57 * All types and defines have been defined in the base/third_party/prtime.h file | 53 * PR_NormalizeTime |
| 58 * These have been copied from the following nspr files. We have only copied over | 54 * PR_GMTParameters |
| 59 * the types we need. | 55 * PR_ImplodeTime |
| 60 * 1. prtime.h | 56 * This was modified to use the Win32 SYSTEMTIME/FILETIME structures |
| 61 * 2. prtypes.h | 57 * and the timezone offsets are applied to the FILETIME structure. |
| 62 * 3. prlong.h | 58 * All types and macros are defined in the base/third_party/prtime.h file. |
| 63 */ | 59 * These have been copied from the following nspr files. We have only copied |
| 60 * over the types we need. |
| 61 * 1. prtime.h |
| 62 * 2. prtypes.h |
| 63 * 3. prlong.h |
| 64 */ |
| 64 | 65 |
| 65 #include "base/third_party/nspr/prtime.h" | 66 #include "base/third_party/nspr/prtime.h" |
| 66 #include "build/build_config.h" | 67 #include "build/build_config.h" |
| 67 | 68 |
| 68 #if defined(OS_WIN) | 69 #if defined(OS_WIN) |
| 69 #include <windows.h> | 70 #include <windows.h> |
| 70 #elif defined(OS_MACOSX) | 71 #elif defined(OS_MACOSX) |
| 71 #include <CoreFoundation/CoreFoundation.h> | 72 #include <CoreFoundation/CoreFoundation.h> |
| 72 #endif | 73 #endif |
| 73 #include <time.h> | 74 #include <time.h> |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 result -= exploded->tm_params.tp_gmt_offset + | 179 result -= exploded->tm_params.tp_gmt_offset + |
| 179 exploded->tm_params.tp_dst_offset; | 180 exploded->tm_params.tp_dst_offset; |
| 180 result *= kSecondsToMicroseconds; | 181 result *= kSecondsToMicroseconds; |
| 181 result += exploded->tm_usec; | 182 result += exploded->tm_usec; |
| 182 return result; | 183 return result; |
| 183 #else | 184 #else |
| 184 #error No PR_ImplodeTime implemented on your platform. | 185 #error No PR_ImplodeTime implemented on your platform. |
| 185 #endif | 186 #endif |
| 186 } | 187 } |
| 187 | 188 |
| 189 /* |
| 190 * The COUNT_LEAPS macro counts the number of leap years passed by |
| 191 * till the start of the given year Y. At the start of the year 4 |
| 192 * A.D. the number of leap years passed by is 0, while at the start of |
| 193 * the year 5 A.D. this count is 1. The number of years divisible by |
| 194 * 100 but not divisible by 400 (the non-leap years) is deducted from |
| 195 * the count to get the correct number of leap years. |
| 196 * |
| 197 * The COUNT_DAYS macro counts the number of days since 01/01/01 till the |
| 198 * start of the given year Y. The number of days at the start of the year |
| 199 * 1 is 0 while the number of days at the start of the year 2 is 365 |
| 200 * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 |
| 201 * midnight 00:00:00. |
| 202 */ |
| 203 |
| 204 #define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) |
| 205 #define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) |
| 206 #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) |
| 207 |
| 208 /* |
| 209 * Static variables used by functions in this file |
| 210 */ |
| 211 |
| 212 /* |
| 213 * The following array contains the day of year for the last day of |
| 214 * each month, where index 1 is January, and day 0 is January 1. |
| 215 */ |
| 216 |
| 217 static const int lastDayOfMonth[2][13] = { |
| 218 {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, |
| 219 {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} |
| 220 }; |
| 221 |
| 222 /* |
| 223 * The number of days in a month |
| 224 */ |
| 225 |
| 226 static const PRInt8 nDays[2][12] = { |
| 227 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, |
| 228 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} |
| 229 }; |
| 230 |
| 231 /* |
| 232 *------------------------------------------------------------------------- |
| 233 * |
| 234 * IsLeapYear -- |
| 235 * |
| 236 * Returns 1 if the year is a leap year, 0 otherwise. |
| 237 * |
| 238 *------------------------------------------------------------------------- |
| 239 */ |
| 240 |
| 241 static int IsLeapYear(PRInt16 year) |
| 242 { |
| 243 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) |
| 244 return 1; |
| 245 else |
| 246 return 0; |
| 247 } |
| 248 |
| 249 /* |
| 250 * 'secOffset' should be less than 86400 (i.e., a day). |
| 251 * 'time' should point to a normalized PRExplodedTime. |
| 252 */ |
| 253 |
| 254 static void |
| 255 ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset) |
| 256 { |
| 257 time->tm_sec += secOffset; |
| 258 |
| 259 /* Note that in this implementation we do not count leap seconds */ |
| 260 if (time->tm_sec < 0 || time->tm_sec >= 60) { |
| 261 time->tm_min += time->tm_sec / 60; |
| 262 time->tm_sec %= 60; |
| 263 if (time->tm_sec < 0) { |
| 264 time->tm_sec += 60; |
| 265 time->tm_min--; |
| 266 } |
| 267 } |
| 268 |
| 269 if (time->tm_min < 0 || time->tm_min >= 60) { |
| 270 time->tm_hour += time->tm_min / 60; |
| 271 time->tm_min %= 60; |
| 272 if (time->tm_min < 0) { |
| 273 time->tm_min += 60; |
| 274 time->tm_hour--; |
| 275 } |
| 276 } |
| 277 |
| 278 if (time->tm_hour < 0) { |
| 279 /* Decrement mday, yday, and wday */ |
| 280 time->tm_hour += 24; |
| 281 time->tm_mday--; |
| 282 time->tm_yday--; |
| 283 if (time->tm_mday < 1) { |
| 284 time->tm_month--; |
| 285 if (time->tm_month < 0) { |
| 286 time->tm_month = 11; |
| 287 time->tm_year--; |
| 288 if (IsLeapYear(time->tm_year)) |
| 289 time->tm_yday = 365; |
| 290 else |
| 291 time->tm_yday = 364; |
| 292 } |
| 293 time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month]; |
| 294 } |
| 295 time->tm_wday--; |
| 296 if (time->tm_wday < 0) |
| 297 time->tm_wday = 6; |
| 298 } else if (time->tm_hour > 23) { |
| 299 /* Increment mday, yday, and wday */ |
| 300 time->tm_hour -= 24; |
| 301 time->tm_mday++; |
| 302 time->tm_yday++; |
| 303 if (time->tm_mday > |
| 304 nDays[IsLeapYear(time->tm_year)][time->tm_month]) { |
| 305 time->tm_mday = 1; |
| 306 time->tm_month++; |
| 307 if (time->tm_month > 11) { |
| 308 time->tm_month = 0; |
| 309 time->tm_year++; |
| 310 time->tm_yday = 0; |
| 311 } |
| 312 } |
| 313 time->tm_wday++; |
| 314 if (time->tm_wday > 6) |
| 315 time->tm_wday = 0; |
| 316 } |
| 317 } |
| 318 |
| 319 void |
| 320 PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) |
| 321 { |
| 322 int daysInMonth; |
| 323 PRInt32 numDays; |
| 324 |
| 325 /* Get back to GMT */ |
| 326 time->tm_sec -= time->tm_params.tp_gmt_offset |
| 327 + time->tm_params.tp_dst_offset; |
| 328 time->tm_params.tp_gmt_offset = 0; |
| 329 time->tm_params.tp_dst_offset = 0; |
| 330 |
| 331 /* Now normalize GMT */ |
| 332 |
| 333 if (time->tm_usec < 0 || time->tm_usec >= 1000000) { |
| 334 time->tm_sec += time->tm_usec / 1000000; |
| 335 time->tm_usec %= 1000000; |
| 336 if (time->tm_usec < 0) { |
| 337 time->tm_usec += 1000000; |
| 338 time->tm_sec--; |
| 339 } |
| 340 } |
| 341 |
| 342 /* Note that we do not count leap seconds in this implementation */ |
| 343 if (time->tm_sec < 0 || time->tm_sec >= 60) { |
| 344 time->tm_min += time->tm_sec / 60; |
| 345 time->tm_sec %= 60; |
| 346 if (time->tm_sec < 0) { |
| 347 time->tm_sec += 60; |
| 348 time->tm_min--; |
| 349 } |
| 350 } |
| 351 |
| 352 if (time->tm_min < 0 || time->tm_min >= 60) { |
| 353 time->tm_hour += time->tm_min / 60; |
| 354 time->tm_min %= 60; |
| 355 if (time->tm_min < 0) { |
| 356 time->tm_min += 60; |
| 357 time->tm_hour--; |
| 358 } |
| 359 } |
| 360 |
| 361 if (time->tm_hour < 0 || time->tm_hour >= 24) { |
| 362 time->tm_mday += time->tm_hour / 24; |
| 363 time->tm_hour %= 24; |
| 364 if (time->tm_hour < 0) { |
| 365 time->tm_hour += 24; |
| 366 time->tm_mday--; |
| 367 } |
| 368 } |
| 369 |
| 370 /* Normalize month and year before mday */ |
| 371 if (time->tm_month < 0 || time->tm_month >= 12) { |
| 372 time->tm_year += time->tm_month / 12; |
| 373 time->tm_month %= 12; |
| 374 if (time->tm_month < 0) { |
| 375 time->tm_month += 12; |
| 376 time->tm_year--; |
| 377 } |
| 378 } |
| 379 |
| 380 /* Now that month and year are in proper range, normalize mday */ |
| 381 |
| 382 if (time->tm_mday < 1) { |
| 383 /* mday too small */ |
| 384 do { |
| 385 /* the previous month */ |
| 386 time->tm_month--; |
| 387 if (time->tm_month < 0) { |
| 388 time->tm_month = 11; |
| 389 time->tm_year--; |
| 390 } |
| 391 time->tm_mday += nDays[IsLeapYear(time->tm_year)][time->tm_month]; |
| 392 } while (time->tm_mday < 1); |
| 393 } else { |
| 394 daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; |
| 395 while (time->tm_mday > daysInMonth) { |
| 396 /* mday too large */ |
| 397 time->tm_mday -= daysInMonth; |
| 398 time->tm_month++; |
| 399 if (time->tm_month > 11) { |
| 400 time->tm_month = 0; |
| 401 time->tm_year++; |
| 402 } |
| 403 daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; |
| 404 } |
| 405 } |
| 406 |
| 407 /* Recompute yday and wday */ |
| 408 time->tm_yday = time->tm_mday + |
| 409 lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; |
| 410 |
| 411 numDays = DAYS_BETWEEN_YEARS(1970, time->tm_year) + time->tm_yday; |
| 412 time->tm_wday = (numDays + 4) % 7; |
| 413 if (time->tm_wday < 0) { |
| 414 time->tm_wday += 7; |
| 415 } |
| 416 |
| 417 /* Recompute time parameters */ |
| 418 |
| 419 time->tm_params = params(time); |
| 420 |
| 421 ApplySecOffset(time, time->tm_params.tp_gmt_offset |
| 422 + time->tm_params.tp_dst_offset); |
| 423 } |
| 424 |
| 425 /* |
| 426 *------------------------------------------------------------------------ |
| 427 * |
| 428 * PR_GMTParameters -- |
| 429 * |
| 430 * Returns the PRTimeParameters for Greenwich Mean Time. |
| 431 * Trivially, both the tp_gmt_offset and tp_dst_offset fields are 0. |
| 432 * |
| 433 *------------------------------------------------------------------------ |
| 434 */ |
| 435 |
| 436 PRTimeParameters |
| 437 PR_GMTParameters(const PRExplodedTime *gmt) |
| 438 { |
| 439 #if defined(XP_MAC) |
| 440 #pragma unused (gmt) |
| 441 #endif |
| 442 |
| 443 PRTimeParameters retVal = { 0, 0 }; |
| 444 return retVal; |
| 445 } |
| 446 |
| 188 /* | 447 /* |
| 189 * The following code implements PR_ParseTimeString(). It is based on | 448 * The following code implements PR_ParseTimeString(). It is based on |
| 190 * ns/lib/xp/xp_time.c, revision 1.25, by Jamie Zawinski <jwz@netscape.com>. | 449 * ns/lib/xp/xp_time.c, revision 1.25, by Jamie Zawinski <jwz@netscape.com>. |
| 191 */ | 450 */ |
| 192 | 451 |
| 193 /* | 452 /* |
| 194 * We only recognize the abbreviations of a small subset of time zones | 453 * We only recognize the abbreviations of a small subset of time zones |
| 195 * in North America, Europe, and Japan. | 454 * in North America, Europe, and Japan. |
| 196 * | 455 * |
| 197 * PST/PDT: Pacific Standard/Daylight Time | 456 * PST/PDT: Pacific Standard/Daylight Time |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 * we consult the `default_to_gmt' to decide whether the string should | 507 * we consult the `default_to_gmt' to decide whether the string should |
| 249 * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). | 508 * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). |
| 250 * The correct value for this argument depends on what standard specified | 509 * The correct value for this argument depends on what standard specified |
| 251 * the time string which you are parsing. | 510 * the time string which you are parsing. |
| 252 */ | 511 */ |
| 253 | 512 |
| 254 PRStatus | 513 PRStatus |
| 255 PR_ParseTimeString( | 514 PR_ParseTimeString( |
| 256 const char *string, | 515 const char *string, |
| 257 PRBool default_to_gmt, | 516 PRBool default_to_gmt, |
| 258 PRTime *result) | 517 PRTime *result_imploded) |
| 259 { | 518 { |
| 260 PRExplodedTime tm; | 519 PRExplodedTime tm; |
| 520 PRExplodedTime *result = &tm; |
| 261 TIME_TOKEN dotw = TT_UNKNOWN; | 521 TIME_TOKEN dotw = TT_UNKNOWN; |
| 262 TIME_TOKEN month = TT_UNKNOWN; | 522 TIME_TOKEN month = TT_UNKNOWN; |
| 263 TIME_TOKEN zone = TT_UNKNOWN; | 523 TIME_TOKEN zone = TT_UNKNOWN; |
| 264 int zone_offset = -1; | 524 int zone_offset = -1; |
| 525 int dst_offset = 0; |
| 265 int date = -1; | 526 int date = -1; |
| 266 PRInt32 year = -1; | 527 PRInt32 year = -1; |
| 267 int hour = -1; | 528 int hour = -1; |
| 268 int min = -1; | 529 int min = -1; |
| 269 int sec = -1; | 530 int sec = -1; |
| 270 | 531 |
| 271 const char *rest = string; | 532 const char *rest = string; |
| 272 | 533 |
| 273 #ifdef DEBUG | |
| 274 int iterations = 0; | 534 int iterations = 0; |
| 275 #endif | |
| 276 | 535 |
| 277 PR_ASSERT(string && result); | 536 PR_ASSERT(string && result); |
| 278 if (!string || !result) return PR_FAILURE; | 537 if (!string || !result) return PR_FAILURE; |
| 279 | 538 |
| 280 while (*rest) | 539 while (*rest) |
| 281 { | 540 { |
| 282 | 541 |
| 283 #ifdef DEBUG | |
| 284 if (iterations++ > 1000) | 542 if (iterations++ > 1000) |
| 285 { | 543 { |
| 286 PR_ASSERT(0); | |
| 287 return PR_FAILURE; | 544 return PR_FAILURE; |
| 288 } | 545 } |
| 289 #endif | |
| 290 | 546 |
| 291 switch (*rest) | 547 switch (*rest) |
| 292 { | 548 { |
| 293 case 'a': case 'A': | 549 case 'a': case 'A': |
| 294 if (month == TT_UNKNOWN && | 550 if (month == TT_UNKNOWN && |
| 295 (rest[1] == 'p' || rest[1] == 'P') && | 551 (rest[1] == 'p' || rest[1] == 'P') && |
| 296 (rest[2] == 'r' || rest[2] == 'R')) | 552 (rest[2] == 'r' || rest[2] == 'R')) |
| 297 month = TT_APR; | 553 month = TT_APR; |
| 298 else if (zone == TT_UNKNOWN && | 554 else if (zone == TT_UNKNOWN && |
| 299 (rest[1] == 's' || rest[1] == 's') && | 555 (rest[1] == 's' || rest[1] == 'S') && |
| 300 (rest[2] == 't' || rest[2] == 'T')) | 556 (rest[2] == 't' || rest[2] == 'T')) |
| 301 zone = TT_AST; | 557 zone = TT_AST; |
| 302 else if (month == TT_UNKNOWN && | 558 else if (month == TT_UNKNOWN && |
| 303 (rest[1] == 'u' || rest[1] == 'U') && | 559 (rest[1] == 'u' || rest[1] == 'U') && |
| 304 (rest[2] == 'g' || rest[2] == 'G')) | 560 (rest[2] == 'g' || rest[2] == 'G')) |
| 305 month = TT_AUG; | 561 month = TT_AUG; |
| 306 break; | 562 break; |
| 307 case 'b': case 'B': | 563 case 'b': case 'B': |
| 308 if (zone == TT_UNKNOWN && | 564 if (zone == TT_UNKNOWN && |
| 309 (rest[1] == 's' || rest[1] == 'S') && | 565 (rest[1] == 's' || rest[1] == 'S') && |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 if (*s < '0' || *s > '9') /* seco
nd 1 or 2 digits */ | 885 if (*s < '0' || *s > '9') /* seco
nd 1 or 2 digits */ |
| 630 break; | 886 break; |
| 631 n2 = (*s++ - '0'); | 887 n2 = (*s++ - '0'); |
| 632 if (*s >= '0' && *s <= '9') | 888 if (*s >= '0' && *s <= '9') |
| 633 n2 = n2*10 + (*s++ - '0'); | 889 n2 = n2*10 + (*s++ - '0'); |
| 634 | 890 |
| 635 if (*s != '/' && *s != '-') /* sl
ash */ | 891 if (*s != '/' && *s != '-') /* sl
ash */ |
| 636 break; | 892 break; |
| 637 s++; | 893 s++; |
| 638 | 894 |
| 639 if (*s < '0' || *s > '9') /* thir
d 1, 2, or 4 digits */ | 895 if (*s < '0' || *s > '9') /* thir
d 1, 2, 4, or 5 digits */ |
| 640 break; | 896 break; |
| 641 n3 = (*s++ - '0'); | 897 n3 = (*s++ - '0'); |
| 642 if (*s >= '0' && *s <= '9') | 898 if (*s >= '0' && *s <= '9') |
| 643 n3 = n3*10 + (*s++ - '0'); | 899 n3 = n3*10 + (*s++ - '0'); |
| 644 | 900 |
| 645 if (*s >= '0' && *s <= '9') /* op
tional digits 3 and 4 */ | 901 if (*s >= '0' && *s <= '9') /* option
al digits 3, 4, and 5 */ |
| 646 { | 902 { |
| 647 n3 = n3*10 + (*s++ - '0'); | 903 n3 = n3*10 + (*s++ - '0'); |
| 648 if (*s < '0' || *s > '9') | 904 if (*s < '0' || *s > '9') |
| 649 break; | 905 break; |
| 650 n3 = n3*10 + (*s++ - '0'); | 906 n3 = n3*10 + (*s++ - '0'); |
| 907 if (*s >= '0' && *s <= '9') |
| 908 n3 = n3*10 + (*s++ - '0'); |
| 651 } | 909 } |
| 652 | 910 |
| 653 if ((*s >= '0' && *s <= '9') || /* follow
ed by non-alphanum */ | 911 if ((*s >= '0' && *s <= '9') || /* follow
ed by non-alphanum */ |
| 654 (*s >= 'A' && *s <= 'Z') || | 912 (*s >= 'A' && *s <= 'Z') || |
| 655 (*s >= 'a' && *s <= 'z')) | 913 (*s >= 'a' && *s <= 'z')) |
| 656 break; | 914 break; |
| 657 | 915 |
| 658 /* Ok, we parsed three 1-2 digit numbers, with /
or - | 916 /* Ok, we parsed three 1-2 digit numbers, with /
or - |
| 659 between them. Now decide what the hell they
are | 917 between them. Now decide what the hell they
are |
| 660 (DD/MM/YY or MM/DD/YY or YY/MM/DD.) | 918 (DD/MM/YY or MM/DD/YY or YY/MM/DD.) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 month = (TIME_TOKEN)(n1 + ((int)TT_JAN)
- 1); | 957 month = (TIME_TOKEN)(n1 + ((int)TT_JAN)
- 1); |
| 700 date = n2; | 958 date = n2; |
| 701 year = n3; | 959 year = n3; |
| 702 } | 960 } |
| 703 rest = s; | 961 rest = s; |
| 704 } | 962 } |
| 705 else if ((*end >= 'A' && *end <= 'Z') || | 963 else if ((*end >= 'A' && *end <= 'Z') || |
| 706 (*end >= 'a' && *end <= 'z')) | 964 (*end >= 'a' && *end <= 'z')) |
| 707 /* Digits followed by non-punctuation - what's that? *
/ | 965 /* Digits followed by non-punctuation - what's that? *
/ |
| 708 ; | 966 ; |
| 967 else if ((end - rest) == 5) /* five digit
s is a year */ |
| 968 year = (year < 0 |
| 969 ? ((rest[0]-'0')*10000L + |
| 970 (rest[1]-'0')*1000L + |
| 971 (rest[2]-'0')*100L + |
| 972 (rest[3]-'0')*10L + |
| 973 (rest[4]-'0')) |
| 974 : year); |
| 709 else if ((end - rest) == 4) /* four digit
s is a year */ | 975 else if ((end - rest) == 4) /* four digit
s is a year */ |
| 710 year = (year < 0 | 976 year = (year < 0 |
| 711 ? ((rest[0]-'0')*1000L + | 977 ? ((rest[0]-'0')*1000L + |
| 712 (rest[1]-'0')*100L + | 978 (rest[1]-'0')*100L + |
| 713 (rest[2]-'0')*10L + | 979 (rest[2]-'0')*10L + |
| 714 (rest[3]-'0')) | 980 (rest[3]-'0')) |
| 715 : year); | 981 : year); |
| 716 else if ((end - rest) == 2) /* two digits
- date or year */ | 982 else if ((end - rest) == 2) /* two digits
- date or year */ |
| 717 { | 983 { |
| 718 int n = ((rest[0]-'0')*10 + | 984 int n = ((rest[0]-'0')*10 + |
| (...skipping 16 matching lines...) Expand all Loading... |
| 735 year = 2000 + n; | 1001 year = 2000 + n; |
| 736 else if (n < 100) | 1002 else if (n < 100) |
| 737 year = 1900 + n; | 1003 year = 1900 + n; |
| 738 else | 1004 else |
| 739 year = n; | 1005 year = n; |
| 740 } | 1006 } |
| 741 /* else what the hell is this. */ | 1007 /* else what the hell is this. */ |
| 742 } | 1008 } |
| 743 else if ((end - rest) == 1) /* one digit
- date */ | 1009 else if ((end - rest) == 1) /* one digit
- date */ |
| 744 date = (date < 0 ? (rest[0]-'0') : date); | 1010 date = (date < 0 ? (rest[0]-'0') : date); |
| 745 /* else, three or more than four digits - what's that? *
/ | 1011 /* else, three or more than five digits - what's that? *
/ |
| 746 | 1012 |
| 747 break; | 1013 break; |
| 748 } | 1014 } |
| 749 } | 1015 } |
| 750 | 1016 |
| 751 /* Skip to the end of this token, whether we parsed it or not. | 1017 /* Skip to the end of this token, whether we parsed it or not. |
| 752 Tokens are delimited by whitespace, or ,;-/ | 1018 Tokens are delimited by whitespace, or ,;-/ |
| 753 But explicitly not :+-. | 1019 But explicitly not :+-. |
| 754 */ | 1020 */ |
| 755 while (*rest && | 1021 while (*rest && |
| 756 *rest != ' ' && *rest != '\t' && | 1022 *rest != ' ' && *rest != '\t' && |
| 757 *rest != ',' && *rest != ';' && | 1023 *rest != ',' && *rest != ';' && |
| 758 *rest != '-' && *rest != '+' && | 1024 *rest != '-' && *rest != '+' && |
| 759 *rest != '/' && | 1025 *rest != '/' && |
| 760 *rest != '(' && *rest != ')' && *rest != '[' && *rest !
= ']') | 1026 *rest != '(' && *rest != ')' && *rest != '[' && *rest !
= ']') |
| 761 rest++; | 1027 rest++; |
| 762 /* skip over uninteresting chars. */ | 1028 /* skip over uninteresting chars. */ |
| 763 SKIP_MORE: | 1029 SKIP_MORE: |
| 764 while (*rest && | 1030 while (*rest && |
| 765 (*rest == ' ' || *rest == '\t' || | 1031 (*rest == ' ' || *rest == '\t' || |
| 766 *rest == ',' || *rest == ';' || *rest == '/' || | 1032 *rest == ',' || *rest == ';' || *rest == '/' || |
| 767 *rest == '(' || *rest == ')' || *rest == '[' || *rest
== ']')) | 1033 *rest == '(' || *rest == ')' || *rest == '[' || *rest
== ']')) |
| 768 rest++; | 1034 rest++; |
| 769 | 1035 |
| 770 /* "-" is ignored at the beginning of a token if we have not yet | 1036 /* "-" is ignored at the beginning of a token if we have not yet |
| 771 parsed a year (e.g., the second "-" in "30-AUG-1966"), or if | 1037 parsed a year (e.g., the second "-" in "30-AUG-1966"), or if |
| 772 the character after the dash is not a digit. */ | 1038 the character after the dash is not a digit. */ |
| 773 if (*rest == '-' && ((rest > string && isalpha(rest[-1]) && year < 0) | 1039 if (*rest == '-' && ((rest > string && isalpha(rest[-1]) && year < 0) |
| 774 || rest[1] < '0' || rest[1] > '9')) | 1040 || rest[1] < '0' || rest[1] > '9')) |
| 775 { | 1041 { |
| 776 rest++; | 1042 rest++; |
| 777 goto SKIP_MORE; | 1043 goto SKIP_MORE; |
| 778 } | 1044 } |
| 779 | 1045 |
| 780 } | 1046 } |
| 781 | 1047 |
| 782 if (zone != TT_UNKNOWN && zone_offset == -1) | 1048 if (zone != TT_UNKNOWN && zone_offset == -1) |
| 783 { | 1049 { |
| 784 switch (zone) | 1050 switch (zone) |
| 785 { | 1051 { |
| 786 case TT_PST: zone_offset = -8 * 60; break; | 1052 case TT_PST: zone_offset = -8 * 60; break; |
| 787 case TT_PDT: zone_offset = -7 * 60; break; | 1053 case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; |
| 788 case TT_MST: zone_offset = -7 * 60; break; | 1054 case TT_MST: zone_offset = -7 * 60; break; |
| 789 case TT_MDT: zone_offset = -6 * 60; break; | 1055 case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; |
| 790 case TT_CST: zone_offset = -6 * 60; break; | 1056 case TT_CST: zone_offset = -6 * 60; break; |
| 791 case TT_CDT: zone_offset = -5 * 60; break; | 1057 case TT_CDT: zone_offset = -6 * 60; dst_offset = 1 * 60; break; |
| 792 case TT_EST: zone_offset = -5 * 60; break; | 1058 case TT_EST: zone_offset = -5 * 60; break; |
| 793 case TT_EDT: zone_offset = -4 * 60; break; | 1059 case TT_EDT: zone_offset = -5 * 60; dst_offset = 1 * 60; break; |
| 794 case TT_AST: zone_offset = -4 * 60; break; | 1060 case TT_AST: zone_offset = -4 * 60; break; |
| 795 case TT_NST: zone_offset = -3 * 60 - 30; break; | 1061 case TT_NST: zone_offset = -3 * 60 - 30; break; |
| 796 case TT_GMT: zone_offset = 0 * 60; break; | 1062 case TT_GMT: zone_offset = 0 * 60; break; |
| 797 case TT_BST: zone_offset = 1 * 60; break; | 1063 case TT_BST: zone_offset = 0 * 60; dst_offset = 1 * 60; break; |
| 798 case TT_MET: zone_offset = 1 * 60; break; | 1064 case TT_MET: zone_offset = 1 * 60; break; |
| 799 case TT_EET: zone_offset = 2 * 60; break; | 1065 case TT_EET: zone_offset = 2 * 60; break; |
| 800 case TT_JST: zone_offset = 9 * 60; break; | 1066 case TT_JST: zone_offset = 9 * 60; break; |
| 801 default: | 1067 default: |
| 802 PR_ASSERT (0); | 1068 PR_ASSERT (0); |
| 803 break; | 1069 break; |
| 804 } | 1070 } |
| 805 } | 1071 } |
| 806 | 1072 |
| 807 /* If we didn't find a year, month, or day-of-the-month, we can't | 1073 /* If we didn't find a year, month, or day-of-the-month, we can't |
| 808 possibly parse this, and in fact, mktime() will do something random | 1074 possibly parse this, and in fact, mktime() will do something random |
| 809 (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt | 1075 (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt |
| 810 a numerologically significant date... */ | 1076 a numerologically significant date... */ |
| 811 if (month == TT_UNKNOWN || date == -1 || year == -1) | 1077 if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) |
| 812 return PR_FAILURE; | 1078 return PR_FAILURE; |
| 813 | 1079 |
| 814 memset(&tm, 0, sizeof(tm)); | 1080 memset(result, 0, sizeof(*result)); |
| 815 if (sec != -1) | 1081 if (sec != -1) |
| 816 tm.tm_sec = sec; | 1082 result->tm_sec = sec; |
| 817 if (min != -1) | 1083 if (min != -1) |
| 818 tm.tm_min = min; | 1084 result->tm_min = min; |
| 819 if (hour != -1) | 1085 if (hour != -1) |
| 820 tm.tm_hour = hour; | 1086 result->tm_hour = hour; |
| 821 if (date != -1) | 1087 if (date != -1) |
| 822 tm.tm_mday = date; | 1088 result->tm_mday = date; |
| 823 if (month != TT_UNKNOWN) | 1089 if (month != TT_UNKNOWN) |
| 824 tm.tm_month = (((int)month) - ((int)TT_JAN)); | 1090 result->tm_month = (((int)month) - ((int)TT_JAN)); |
| 825 if (year != -1) | 1091 if (year != -1) |
| 826 tm.tm_year = year; | 1092 result->tm_year = year; |
| 827 if (dotw != TT_UNKNOWN) | 1093 if (dotw != TT_UNKNOWN) |
| 828 tm.tm_wday = (((int)dotw) - ((int)TT_SUN)); | 1094 result->tm_wday = (((int)dotw) - ((int)TT_SUN)); |
| 829 | 1095 |
| 830 if (zone == TT_UNKNOWN && default_to_gmt) | 1096 if (zone == TT_UNKNOWN && default_to_gmt) |
| 831 { | 1097 { |
| 832 /* No zone was specified, so pretend the zone was GMT. */ | 1098 /* No zone was specified, so pretend the zone was GMT. */ |
| 833 zone = TT_GMT; | 1099 zone = TT_GMT; |
| 834 zone_offset = 0; | 1100 zone_offset = 0; |
| 835 } | 1101 } |
| 836 | 1102 |
| 837 if (zone_offset == -1) | 1103 if (zone_offset == -1) |
| 838 { | 1104 { |
| 839 /* no zone was specified, and we're to assume that everything | 1105 /* no zone was specified, and we're to assume that everything |
| 840 is local. */ | 1106 is local. */ |
| 841 struct tm localTime; | 1107 struct tm localTime; |
| 842 time_t secs; | 1108 time_t secs; |
| 843 | 1109 |
| 844 PR_ASSERT(tm.tm_month > -1 | 1110 PR_ASSERT(result->tm_month > -1 && |
| 845 && tm.tm_mday > 0 | 1111 result->tm_mday > 0 && |
| 846 && tm.tm_hour > -1 | 1112 result->tm_hour > -1 && |
| 847 && tm.tm_min > -1 | 1113 result->tm_min > -1 && |
| 848 && tm.tm_sec > -1); | 1114 result->tm_sec > -1); |
| 849 | 1115 |
| 850 /* | 1116 /* |
| 851 * To obtain time_t from a tm structure representing the local | 1117 * To obtain time_t from a tm structure representing the local |
| 852 * time, we call mktime(). However, we need to see if we are | 1118 * time, we call mktime(). However, we need to see if we are |
| 853 * on 1-Jan-1970 or before. If we are, we can't call mktime() | 1119 * on 1-Jan-1970 or before. If we are, we can't call mktime() |
| 854 * because mktime() will crash on win16. In that case, we | 1120 * because mktime() will crash on win16. In that case, we |
| 855 * calculate zone_offset based on the zone offset at | 1121 * calculate zone_offset based on the zone offset at |
| 856 * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the | 1122 * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the |
| 857 * date we are parsing to transform the date to GMT. We also | 1123 * date we are parsing to transform the date to GMT. We also |
| 858 * do so if mktime() returns (time_t) -1 (time out of range). | 1124 * do so if mktime() returns (time_t) -1 (time out of range). |
| 859 */ | 1125 */ |
| 860 | 1126 |
| 861 /* month, day, hours, mins and secs are always non-negative | 1127 /* month, day, hours, mins and secs are always non-negative |
| 862 so we dont need to worry about them. */ | 1128 so we dont need to worry about them. */ |
| 863 if(tm.tm_year >= 1970) | 1129 if(result->tm_year >= 1970) |
| 864 { | 1130 { |
| 865 PRInt64 usec_per_sec; | 1131 PRInt64 usec_per_sec; |
| 866 | 1132 |
| 867 localTime.tm_sec = tm.tm_sec; | 1133 localTime.tm_sec = result->tm_sec; |
| 868 localTime.tm_min = tm.tm_min; | 1134 localTime.tm_min = result->tm_min; |
| 869 localTime.tm_hour = tm.tm_hour; | 1135 localTime.tm_hour = result->tm_hour; |
| 870 localTime.tm_mday = tm.tm_mday; | 1136 localTime.tm_mday = result->tm_mday; |
| 871 localTime.tm_mon = tm.tm_month; | 1137 localTime.tm_mon = result->tm_month; |
| 872 localTime.tm_year = tm.tm_year - 1900; | 1138 localTime.tm_year = result->tm_year - 1900; |
| 873 /* Set this to -1 to tell mktime "I don't care". If you set | 1139 /* Set this to -1 to tell mktime "I don't care". If you set |
| 874 it to 0 or 1, you are making assertions about whether the | 1140 it to 0 or 1, you are making assertions about whether the |
| 875 date you are handing it is in daylight savings mode or not; | 1141 date you are handing it is in daylight savings mode or not; |
| 876 and if you're wrong, it will "fix" it for you. */ | 1142 and if you're wrong, it will "fix" it for you. */ |
| 877 localTime.tm_isdst = -1; | 1143 localTime.tm_isdst = -1; |
| 878 secs = mktime(&localTime); | 1144 secs = mktime(&localTime); |
| 879 if (secs != (time_t) -1) | 1145 if (secs != (time_t) -1) |
| 880 { | 1146 { |
| 881 #if defined(XP_MAC) && (__MSL__ < 0x6000) | 1147 PRTime usecs64; |
| 882 /* | 1148 LL_I2L(usecs64, secs); |
| 883 * The mktime() routine in MetroWerks MSL C | |
| 884 * Runtime library returns seconds since midnight, | |
| 885 * 1 Jan. 1900, not 1970 - in versions of MSL (Metrowerks
Standard | |
| 886 * Library) prior to version 6. Only for older versions o
f | |
| 887 * MSL do we adjust the value of secs to the NSPR epoch | |
| 888 */ | |
| 889 secs -= ((365 * 70UL) + 17) * 24 * 60 * 60; | |
| 890 #endif | |
| 891 LL_I2L(*result, secs); | |
| 892 LL_I2L(usec_per_sec, PR_USEC_PER_SEC); | 1149 LL_I2L(usec_per_sec, PR_USEC_PER_SEC); |
| 893 LL_MUL(*result, *result, usec_per_sec); | 1150 LL_MUL(usecs64, usecs64, usec_per_sec); |
| 1151 *result_imploded = usecs64; |
| 894 return PR_SUCCESS; | 1152 return PR_SUCCESS; |
| 895 } | 1153 } |
| 896 } | 1154 } |
| 897 | 1155 |
| 898 /* So mktime() can't handle this case. We assume the | 1156 /* So mktime() can't handle this case. We assume the |
| 899 zone_offset for the date we are parsing is the same as | 1157 zone_offset for the date we are parsing is the same as |
| 900 the zone offset on 00:00:00 2 Jan 1970 GMT. */ | 1158 the zone offset on 00:00:00 2 Jan 1970 GMT. */ |
| 901 secs = 86400; | 1159 secs = 86400; |
| 902 localtime_r(&secs, &localTime); | 1160 localtime_r(&secs, &localTime); |
| 903 zone_offset = localTime.tm_min | 1161 zone_offset = localTime.tm_min |
| 904 + 60 * localTime.tm_hour | 1162 + 60 * localTime.tm_hour |
| 905 + 1440 * (localTime.tm_mday - 2); | 1163 + 1440 * (localTime.tm_mday - 2); |
| 906 } | 1164 } |
| 907 | 1165 |
| 908 tm.tm_params.tp_gmt_offset = zone_offset * 60; | 1166 /* mainly to compute wday and yday */ |
| 1167 PR_NormalizeTime(result, PR_GMTParameters); |
| 1168 result->tm_params.tp_gmt_offset = zone_offset * 60; |
| 1169 result->tm_params.tp_dst_offset = dst_offset * 60; |
| 909 | 1170 |
| 910 *result = PR_ImplodeTime(&tm); | 1171 *result_imploded = PR_ImplodeTime(result); |
| 911 | |
| 912 return PR_SUCCESS; | 1172 return PR_SUCCESS; |
| 913 } | 1173 } |
| OLD | NEW |