OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |