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

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

Issue 266193002: Extend PR_ParseTimeString() to accept some ISO 8601 formats to fix timezone parsing in SyslogParser. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix microsecond parsing for Windows and for timezoneless (local time) inputs. Created 6 years, 7 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
OLDNEW
1 /* Portions are Copyright (C) 2011 Google Inc */ 1 /* Portions are Copyright (C) 2011 Google Inc */
2 /* ***** BEGIN LICENSE BLOCK ***** 2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * 4 *
5 * The contents of this file are subject to the Mozilla Public License Version 5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with 6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at 7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/ 8 * http://www.mozilla.org/MPL/
9 * 9 *
10 * Software distributed under the License is distributed on an "AS IS" basis, 10 * Software distributed under the License is distributed on an "AS IS" basis,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 * PR_GMTParameters 54 * PR_GMTParameters
55 * PR_ImplodeTime 55 * PR_ImplodeTime
56 * This was modified to use the Win32 SYSTEMTIME/FILETIME structures 56 * This was modified to use the Win32 SYSTEMTIME/FILETIME structures
57 * and the timezone offsets are applied to the FILETIME structure. 57 * and the timezone offsets are applied to the FILETIME structure.
58 * All types and macros are defined in the base/third_party/prtime.h file. 58 * All types and macros are defined in the base/third_party/prtime.h file.
59 * These have been copied from the following nspr files. We have only copied 59 * These have been copied from the following nspr files. We have only copied
60 * over the types we need. 60 * over the types we need.
61 * 1. prtime.h 61 * 1. prtime.h
62 * 2. prtypes.h 62 * 2. prtypes.h
63 * 3. prlong.h 63 * 3. prlong.h
64 *
65 * Unit tests are in base/time/pr_time_unittest.cc.
64 */ 66 */
65 67
66 #include "base/logging.h" 68 #include "base/logging.h"
67 #include "base/third_party/nspr/prtime.h" 69 #include "base/third_party/nspr/prtime.h"
68 #include "build/build_config.h" 70 #include "build/build_config.h"
69 71
70 #if defined(OS_WIN) 72 #if defined(OS_WIN)
71 #include <windows.h> 73 #include <windows.h>
72 #elif defined(OS_MACOSX) 74 #elif defined(OS_MACOSX)
73 #include <CoreFoundation/CoreFoundation.h> 75 #include <CoreFoundation/CoreFoundation.h>
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 // Apply offsets. 127 // Apply offsets.
126 uli.LowPart = ft.dwLowDateTime; 128 uli.LowPart = ft.dwLowDateTime;
127 uli.HighPart = ft.dwHighDateTime; 129 uli.HighPart = ft.dwHighDateTime;
128 // Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units 130 // Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units
129 // to microsecond units. 131 // to microsecond units.
130 PRTime result = 132 PRTime result =
131 static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64); 133 static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64);
132 // Adjust for time zone and dst. Convert from seconds to microseconds. 134 // Adjust for time zone and dst. Convert from seconds to microseconds.
133 result -= (exploded->tm_params.tp_gmt_offset + 135 result -= (exploded->tm_params.tp_gmt_offset +
134 exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds; 136 exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds;
137 // Add microseconds that cannot be represented in |st|.
138 result += exploded->tm_usec % 1000;
135 return result; 139 return result;
136 #elif defined(OS_MACOSX) 140 #elif defined(OS_MACOSX)
137 // Create the system struct representing our exploded time. 141 // Create the system struct representing our exploded time.
138 CFGregorianDate gregorian_date; 142 CFGregorianDate gregorian_date;
139 gregorian_date.year = exploded->tm_year; 143 gregorian_date.year = exploded->tm_year;
140 gregorian_date.month = exploded->tm_month + 1; 144 gregorian_date.month = exploded->tm_month + 1;
141 gregorian_date.day = exploded->tm_mday; 145 gregorian_date.day = exploded->tm_mday;
142 gregorian_date.hour = exploded->tm_hour; 146 gregorian_date.hour = exploded->tm_hour;
143 gregorian_date.minute = exploded->tm_min; 147 gregorian_date.minute = exploded->tm_min;
144 gregorian_date.second = exploded->tm_sec; 148 gregorian_date.second = exploded->tm_sec;
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 * Mon Jan 16 16:12 +0130 1989 502 * Mon Jan 16 16:12 +0130 1989
499 * 6 May 1992 16:41-JST (Wednesday) 503 * 6 May 1992 16:41-JST (Wednesday)
500 * 22-AUG-1993 10:59:12.82 504 * 22-AUG-1993 10:59:12.82
501 * 22-AUG-1993 10:59pm 505 * 22-AUG-1993 10:59pm
502 * 22-AUG-1993 12:59am 506 * 22-AUG-1993 12:59am
503 * 22-AUG-1993 12:59 PM 507 * 22-AUG-1993 12:59 PM
504 * Friday, August 04, 1995 3:54 PM 508 * Friday, August 04, 1995 3:54 PM
505 * 06/21/95 04:24:34 PM 509 * 06/21/95 04:24:34 PM
506 * 20/06/95 21:07 510 * 20/06/95 21:07
507 * 95-06-08 19:32:48 EDT 511 * 95-06-08 19:32:48 EDT
512 * 1995-06-17T23:11:25.342156Z
508 * 513 *
509 * If the input string doesn't contain a description of the timezone, 514 * If the input string doesn't contain a description of the timezone,
510 * we consult the `default_to_gmt' to decide whether the string should 515 * we consult the `default_to_gmt' to decide whether the string should
511 * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). 516 * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE).
512 * The correct value for this argument depends on what standard specified 517 * The correct value for this argument depends on what standard specified
513 * the time string which you are parsing. 518 * the time string which you are parsing.
514 */ 519 */
515 520
516 PRStatus 521 PRStatus
517 PR_ParseTimeString( 522 PR_ParseTimeString(
518 const char *string, 523 const char *string,
519 PRBool default_to_gmt, 524 PRBool default_to_gmt,
520 PRTime *result_imploded) 525 PRTime *result_imploded)
521 { 526 {
522 PRExplodedTime tm; 527 PRExplodedTime tm;
523 PRExplodedTime *result = &tm; 528 PRExplodedTime *result = &tm;
524 TIME_TOKEN dotw = TT_UNKNOWN; 529 TIME_TOKEN dotw = TT_UNKNOWN;
525 TIME_TOKEN month = TT_UNKNOWN; 530 TIME_TOKEN month = TT_UNKNOWN;
526 TIME_TOKEN zone = TT_UNKNOWN; 531 TIME_TOKEN zone = TT_UNKNOWN;
527 int zone_offset = -1; 532 int zone_offset = -1;
528 int dst_offset = 0; 533 int dst_offset = 0;
529 int date = -1; 534 int date = -1;
530 PRInt32 year = -1; 535 PRInt32 year = -1;
531 int hour = -1; 536 int hour = -1;
532 int min = -1; 537 int min = -1;
533 int sec = -1; 538 int sec = -1;
539 int usec = -1;
534 540
535 const char *rest = string; 541 const char *rest = string;
536 542
537 int iterations = 0; 543 int iterations = 0;
538 544
539 PR_ASSERT(string && result); 545 PR_ASSERT(string && result);
540 if (!string || !result) return PR_FAILURE; 546 if (!string || !result) return PR_FAILURE;
541 547
542 while (*rest) 548 while (*rest)
543 { 549 {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 zone = TT_GMT; 773 zone = TT_GMT;
768 break; 774 break;
769 } 775 }
770 776
771 case '0': case '1': case '2': case '3': case '4': 777 case '0': case '1': case '2': case '3': case '4':
772 case '5': case '6': case '7': case '8': case '9': 778 case '5': case '6': case '7': case '8': case '9':
773 { 779 {
774 int tmp_hour = -1; 780 int tmp_hour = -1;
775 int tmp_min = -1; 781 int tmp_min = -1;
776 int tmp_sec = -1; 782 int tmp_sec = -1;
783 int tmp_usec = -1;
777 const char *end = rest + 1; 784 const char *end = rest + 1;
778 while (*end >= '0' && *end <= '9') 785 while (*end >= '0' && *end <= '9')
779 end++; 786 end++;
780 787
781 /* end is now the first character after a range of digit s. */ 788 /* end is now the first character after a range of digit s. */
782 789
783 if (*end == ':') 790 if (*end == ':')
784 { 791 {
785 if (hour >= 0 && min >= 0) /* already got it */ 792 if (hour >= 0 && min >= 0) /* already got it */
786 break; 793 break;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 ; 833 ;
827 else if ((end - rest) > 2) 834 else if ((end - rest) > 2)
828 /* it is [0-9][0-9][0-9]+: */ 835 /* it is [0-9][0-9][0-9]+: */
829 break; 836 break;
830 else if ((end - rest) == 2) 837 else if ((end - rest) == 2)
831 tmp_sec = ((rest[0]-'0')*10 + 838 tmp_sec = ((rest[0]-'0')*10 +
832 (rest[1]-'0')); 839 (rest[1]-'0'));
833 else 840 else
834 tmp_sec = (rest[0]-'0'); 841 tmp_sec = (rest[0]-'0');
835 842
836 /* If we made it here, we've parsed hour and min , 843 /* fractional second */
837 and possibly sec, so it worked as a unit. */ 844 rest = end;
845 if (*rest == '.')
846 {
847 rest++;
848 end++;
849 tmp_usec = 0;
850 /* use up to 6 digits, skip over the rest */
851 while (*end >= '0' && *end <= '9')
852 {
853 if (end - rest < 6)
854 tmp_usec = tmp_usec * 10 + *end - '0';
855 end++;
856 }
857 int ndigits = end - rest;
858 while (ndigits++ < 6)
859 tmp_usec *= 10;
860 rest = end;
861 }
838 862
839 /* skip over whitespace and see if there's an AM or PM 863 if (*rest == 'Z')
840 directly following the time.
841 */
842 if (tmp_hour <= 12)
843 { 864 {
865 zone = TT_GMT;
866 rest++;
867 }
868 else if (tmp_hour <= 12)
869 {
870 /* If we made it here, we've parsed hour and min,
871 and possibly sec, so the current token is a time.
872 Now skip over whitespace and see if there 's an AM
873 or PM directly following the time.
874 */
844 const char *s = end; 875 const char *s = end;
845 while (*s && (*s == ' ' || *s == '\t')) 876 while (*s && (*s == ' ' || *s == '\t'))
846 s++; 877 s++;
847 if ((s[0] == 'p' || s[0] == 'P') && 878 if ((s[0] == 'p' || s[0] == 'P') &&
848 (s[1] == 'm' || s[1] == 'M')) 879 (s[1] == 'm' || s[1] == 'M'))
849 /* 10:05pm == 22:05, and 12:05pm == 12 :05 */ 880 /* 10:05pm == 22:05, and 12:05pm == 12 :05 */
850 tmp_hour = (tmp_hour == 12 ? 12 : tmp_ hour + 12); 881 tmp_hour = (tmp_hour == 12 ? 12 : tmp_ hour + 12);
851 else if (tmp_hour == 12 && 882 else if (tmp_hour == 12 &&
852 (s[0] == 'a' || s[0] == 'A') && 883 (s[0] == 'a' || s[0] == 'A') &&
853 (s[1] == 'm' || s[1] == 'M')) 884 (s[1] == 'm' || s[1] == 'M'))
854 /* 12:05am == 00:05 */ 885 /* 12:05am == 00:05 */
855 tmp_hour = 0; 886 tmp_hour = 0;
856 } 887 }
857 888
858 hour = tmp_hour; 889 hour = tmp_hour;
859 min = tmp_min; 890 min = tmp_min;
860 sec = tmp_sec; 891 sec = tmp_sec;
892 usec = tmp_usec;
861 rest = end; 893 rest = end;
862 break; 894 break;
863 } 895 }
864 else if ((*end == '/' || *end == '-') && 896 else if ((*end == '/' || *end == '-') &&
865 end[1] >= '0' && end[1] <= '9') 897 end[1] >= '0' && end[1] <= '9')
866 { 898 {
867 /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 899 /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95
868 or even 95-06-05... 900 or even 95-06-05 or 1995-06-22.
869 #### But it doesn't handle 1995-06-22.
870 */ 901 */
871 int n1, n2, n3; 902 int n1, n2, n3;
872 const char *s; 903 const char *s;
873 904
874 if (month != TT_UNKNOWN) 905 if (month != TT_UNKNOWN)
875 /* if we saw a month name, this can't be. */ 906 /* if we saw a month name, this can't be. */
876 break; 907 break;
877 908
878 s = rest; 909 s = rest;
879 910
880 n1 = (*s++ - '0'); /* first 1 or 2 digits */ 911 n1 = (*s++ - '0'); /* first 1, 2 or 4 digits */
881 if (*s >= '0' && *s <= '9') 912 if (*s >= '0' && *s <= '9')
882 n1 = n1*10 + (*s++ - '0'); 913 {
914 n1 = n1*10 + (*s++ - '0');
915
916 if (*s >= '0' && *s <= '9') /* op tional digits 3 and 4 */
917 {
918 n1 = n1*10 + (*s++ - '0');
919 if (*s < '0' || *s > '9')
920 break;
921 n1 = n1*10 + (*s++ - '0');
922 }
923 }
883 924
884 if (*s != '/' && *s != '-') /* sl ash */ 925 if (*s != '/' && *s != '-') /* sl ash */
885 break; 926 break;
886 s++; 927 s++;
887 928
888 if (*s < '0' || *s > '9') /* seco nd 1 or 2 digits */ 929 if (*s < '0' || *s > '9') /* seco nd 1 or 2 digits */
889 break; 930 break;
890 n2 = (*s++ - '0'); 931 n2 = (*s++ - '0');
891 if (*s >= '0' && *s <= '9') 932 if (*s >= '0' && *s <= '9')
892 n2 = n2*10 + (*s++ - '0'); 933 n2 = n2*10 + (*s++ - '0');
(...skipping 11 matching lines...) Expand all
904 if (*s >= '0' && *s <= '9') /* option al digits 3, 4, and 5 */ 945 if (*s >= '0' && *s <= '9') /* option al digits 3, 4, and 5 */
905 { 946 {
906 n3 = n3*10 + (*s++ - '0'); 947 n3 = n3*10 + (*s++ - '0');
907 if (*s < '0' || *s > '9') 948 if (*s < '0' || *s > '9')
908 break; 949 break;
909 n3 = n3*10 + (*s++ - '0'); 950 n3 = n3*10 + (*s++ - '0');
910 if (*s >= '0' && *s <= '9') 951 if (*s >= '0' && *s <= '9')
911 n3 = n3*10 + (*s++ - '0'); 952 n3 = n3*10 + (*s++ - '0');
912 } 953 }
913 954
914 if ((*s >= '0' && *s <= '9') || /* follow ed by non-alphanum */ 955 if (*s == 'T' && s[1] >= '0' && s[1] <= '9')
915 (*s >= 'A' && *s <= 'Z') || 956 /* followed by ISO 8601 T delimiter and number is ok */
916 (*s >= 'a' && *s <= 'z')) 957 ;
958 else if ((*s >= '0' && *s <= '9') ||
959 (*s >= 'A' && *s <= 'Z') ||
960 (*s >= 'a' && *s <= 'z'))
961 /* but other alphanumerics are not ok */
917 break; 962 break;
918 963
919 /* Ok, we parsed three 1-2 digit numbers, with / or - 964 /* Ok, we parsed three multi-digit numbers, with / or -
920 between them. Now decide what the hell they are 965 between them. Now decide what the hell they are
921 (DD/MM/YY or MM/DD/YY or YY/MM/DD.) 966 (DD/MM/YY or MM/DD/YY or [YY]YY/MM/DD.)
922 */ 967 */
923 968
924 if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ 969 if (n1 > 31 || n1 == 0) /* must be [YY]YY/MM/DD */
925 { 970 {
926 if (n2 > 12) break; 971 if (n2 > 12) break;
927 if (n3 > 31) break; 972 if (n3 > 31) break;
928 year = n1; 973 year = n1;
929 if (year < 70) 974 if (year < 70)
930 year += 2000; 975 year += 2000;
931 else if (year < 100) 976 else if (year < 100)
932 year += 1900; 977 year += 1900;
933 month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); 978 month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1);
934 date = n3; 979 date = n3;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 else 1052 else
1008 year = n; 1053 year = n;
1009 } 1054 }
1010 /* else what the hell is this. */ 1055 /* else what the hell is this. */
1011 } 1056 }
1012 else if ((end - rest) == 1) /* one digit - date */ 1057 else if ((end - rest) == 1) /* one digit - date */
1013 date = (date < 0 ? (rest[0]-'0') : date); 1058 date = (date < 0 ? (rest[0]-'0') : date);
1014 /* else, three or more than five digits - what's that? * / 1059 /* else, three or more than five digits - what's that? * /
1015 1060
1016 break; 1061 break;
1017 } 1062 } /* case '0' .. '9' */
1018 } 1063 } /* switch */
1019 1064
1020 /* Skip to the end of this token, whether we parsed it or not. 1065 /* Skip to the end of this token, whether we parsed it or not.
1021 Tokens are delimited by whitespace, or ,;-/ 1066 Tokens are delimited by whitespace, or ,;-+/()[] but explicitly not .:
1022 But explicitly not :+-. 1067 'T' is also treated as delimiter when followed by a digit (ISO 8601 ).
1023 */ 1068 */
1024 while (*rest && 1069 while (*rest &&
1025 *rest != ' ' && *rest != '\t' && 1070 *rest != ' ' && *rest != '\t' &&
1026 *rest != ',' && *rest != ';' && 1071 *rest != ',' && *rest != ';' &&
1027 *rest != '-' && *rest != '+' && 1072 *rest != '-' && *rest != '+' &&
1028 *rest != '/' && 1073 *rest != '/' &&
1029 *rest != '(' && *rest != ')' && *rest != '[' && *rest ! = ']') 1074 *rest != '(' && *rest != ')' && *rest != '[' && *rest ! = ']' &&
1075 !(*rest == 'T' && rest[1] >= '0' && rest[1] <= '9')
1076 )
1030 rest++; 1077 rest++;
1031 /* skip over uninteresting chars. */ 1078 /* skip over uninteresting chars. */
1032 SKIP_MORE: 1079 SKIP_MORE:
1033 while (*rest && 1080 while (*rest == ' ' || *rest == '\t' ||
1034 (*rest == ' ' || *rest == '\t' || 1081 *rest == ',' || *rest == ';' || *rest == '/' ||
1035 *rest == ',' || *rest == ';' || *rest == '/' || 1082 *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')
1036 *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']'))
1037 rest++; 1083 rest++;
1038 1084
1039 /* "-" is ignored at the beginning of a token if we have not yet 1085 /* "-" is ignored at the beginning of a token if we have not yet
1040 parsed a year (e.g., the second "-" in "30-AUG-1966"), or if 1086 parsed a year (e.g., the second "-" in "30-AUG-1966"), or if
1041 the character after the dash is not a digit. */ 1087 the character after the dash is not a digit. */
1042 if (*rest == '-' && ((rest > string && 1088 if (*rest == '-' && ((rest > string &&
1043 isalpha((unsigned char)rest[-1]) && year < 0) || 1089 isalpha((unsigned char)rest[-1]) && year < 0) ||
1044 rest[1] < '0' || rest[1] > '9')) 1090 rest[1] < '0' || rest[1] > '9'))
1045 { 1091 {
1046 rest++; 1092 rest++;
1047 goto SKIP_MORE; 1093 goto SKIP_MORE;
1048 } 1094 }
1049 1095
1050 } 1096 /* Skip T that may precede ISO 8601 time. */
1097 if (*rest == 'T' && rest[1] >= '0' && rest[1] <= '9')
1098 rest++;
1099 } /* while */
1051 1100
1052 if (zone != TT_UNKNOWN && zone_offset == -1) 1101 if (zone != TT_UNKNOWN && zone_offset == -1)
1053 { 1102 {
1054 switch (zone) 1103 switch (zone)
1055 { 1104 {
1056 case TT_PST: zone_offset = -8 * 60; break; 1105 case TT_PST: zone_offset = -8 * 60; break;
1057 case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; 1106 case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break;
1058 case TT_MST: zone_offset = -7 * 60; break; 1107 case TT_MST: zone_offset = -7 * 60; break;
1059 case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; 1108 case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break;
1060 case TT_CST: zone_offset = -6 * 60; break; 1109 case TT_CST: zone_offset = -6 * 60; break;
(...skipping 14 matching lines...) Expand all
1075 } 1124 }
1076 1125
1077 /* If we didn't find a year, month, or day-of-the-month, we can't 1126 /* If we didn't find a year, month, or day-of-the-month, we can't
1078 possibly parse this, and in fact, mktime() will do something random 1127 possibly parse this, and in fact, mktime() will do something random
1079 (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt 1128 (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt
1080 a numerologically significant date... */ 1129 a numerologically significant date... */
1081 if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) 1130 if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX)
1082 return PR_FAILURE; 1131 return PR_FAILURE;
1083 1132
1084 memset(result, 0, sizeof(*result)); 1133 memset(result, 0, sizeof(*result));
1134 if (usec != -1)
1135 result->tm_usec = usec;
1085 if (sec != -1) 1136 if (sec != -1)
1086 result->tm_sec = sec; 1137 result->tm_sec = sec;
1087 if (min != -1) 1138 if (min != -1)
1088 result->tm_min = min; 1139 result->tm_min = min;
1089 if (hour != -1) 1140 if (hour != -1)
1090 result->tm_hour = hour; 1141 result->tm_hour = hour;
1091 if (date != -1) 1142 if (date != -1)
1092 result->tm_mday = date; 1143 result->tm_mday = date;
1093 if (month != TT_UNKNOWN) 1144 if (month != TT_UNKNOWN)
1094 result->tm_month = (((int)month) - ((int)TT_JAN)); 1145 result->tm_month = (((int)month) - ((int)TT_JAN));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 * time, we call mktime(). However, we need to see if we are 1179 * time, we call mktime(). However, we need to see if we are
1129 * on 1-Jan-1970 or before. If we are, we can't call mktime() 1180 * on 1-Jan-1970 or before. If we are, we can't call mktime()
1130 * because mktime() will crash on win16. In that case, we 1181 * because mktime() will crash on win16. In that case, we
1131 * calculate zone_offset based on the zone offset at 1182 * calculate zone_offset based on the zone offset at
1132 * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the 1183 * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the
1133 * date we are parsing to transform the date to GMT. We also 1184 * date we are parsing to transform the date to GMT. We also
1134 * do so if mktime() returns (time_t) -1 (time out of range). 1185 * do so if mktime() returns (time_t) -1 (time out of range).
1135 */ 1186 */
1136 1187
1137 /* month, day, hours, mins and secs are always non-negative 1188 /* month, day, hours, mins and secs are always non-negative
1138 so we dont need to worry about them. */ 1189 so we dont need to worry about them. */
1139 if(result->tm_year >= 1970) 1190 if (result->tm_year >= 1970)
1140 { 1191 {
1141 PRInt64 usec_per_sec;
1142
1143 localTime.tm_sec = result->tm_sec; 1192 localTime.tm_sec = result->tm_sec;
1144 localTime.tm_min = result->tm_min; 1193 localTime.tm_min = result->tm_min;
1145 localTime.tm_hour = result->tm_hour; 1194 localTime.tm_hour = result->tm_hour;
1146 localTime.tm_mday = result->tm_mday; 1195 localTime.tm_mday = result->tm_mday;
1147 localTime.tm_mon = result->tm_month; 1196 localTime.tm_mon = result->tm_month;
1148 localTime.tm_year = result->tm_year - 1900; 1197 localTime.tm_year = result->tm_year - 1900;
1149 /* Set this to -1 to tell mktime "I don't care". If you set 1198 /* Set this to -1 to tell mktime "I don't care". If you set
1150 it to 0 or 1, you are making assertions about whether the 1199 it to 0 or 1, you are making assertions about whether the
1151 date you are handing it is in daylight savings mode or not; 1200 date you are handing it is in daylight savings mode or not;
1152 and if you're wrong, it will "fix" it for you. */ 1201 and if you're wrong, it will "fix" it for you. */
(...skipping 19 matching lines...) Expand all
1172 errno = EINVAL; 1221 errno = EINVAL;
1173 secs = (time_t) -1; 1222 secs = (time_t) -1;
1174 } else { 1223 } else {
1175 secs = mktime(&localTime); 1224 secs = mktime(&localTime);
1176 } 1225 }
1177 #else 1226 #else
1178 secs = mktime(&localTime); 1227 secs = mktime(&localTime);
1179 #endif 1228 #endif
1180 if (secs != (time_t) -1) 1229 if (secs != (time_t) -1)
1181 { 1230 {
1182 PRTime usecs64; 1231 *result_imploded = (PRInt64)secs * PR_USEC_PER_SEC;
1183 LL_I2L(usecs64, secs); 1232 *result_imploded += result->tm_usec;
1184 LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
1185 LL_MUL(usecs64, usecs64, usec_per_sec);
1186 *result_imploded = usecs64;
1187 return PR_SUCCESS; 1233 return PR_SUCCESS;
1188 } 1234 }
1189 } 1235 }
1190 1236
1191 /* So mktime() can't handle this case. We assume the 1237 /* So mktime() can't handle this case. We assume the
1192 zone_offset for the date we are parsing is the same as 1238 zone_offset for the date we are parsing is the same as
1193 the zone offset on 00:00:00 2 Jan 1970 GMT. */ 1239 the zone offset on 00:00:00 2 Jan 1970 GMT. */
1194 secs = 86400; 1240 secs = 86400;
1195 localtime_r(&secs, &localTime); 1241 localtime_r(&secs, &localTime);
1196 zone_offset = localTime.tm_min 1242 zone_offset = localTime.tm_min
1197 + 60 * localTime.tm_hour 1243 + 60 * localTime.tm_hour
1198 + 1440 * (localTime.tm_mday - 2); 1244 + 1440 * (localTime.tm_mday - 2);
1199 } 1245 }
1200 1246
1201 result->tm_params.tp_gmt_offset = zone_offset * 60; 1247 result->tm_params.tp_gmt_offset = zone_offset * 60;
1202 result->tm_params.tp_dst_offset = dst_offset * 60; 1248 result->tm_params.tp_dst_offset = dst_offset * 60;
1203 1249
1204 *result_imploded = PR_ImplodeTime(result); 1250 *result_imploded = PR_ImplodeTime(result);
1205 return PR_SUCCESS; 1251 return PR_SUCCESS;
1206 } 1252 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698