Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(550)

Side by Side Diff: base/third_party/nspr/prtime.cc

Issue 27339: Merge the latest version of PR_ParseTimeString.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/third_party/nspr/prtime.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « base/third_party/nspr/prtime.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698