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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 /* | 47 /* |
48 * The following functions were copied from the NSPR prtime.c file. | 48 * The following functions were copied from the NSPR prtime.c file. |
49 * PR_ParseTimeString | 49 * PR_ParseTimeString |
50 * We inlined the new PR_ParseTimeStringToExplodedTime function to avoid | 50 * We inlined the new PR_ParseTimeStringToExplodedTime function to avoid |
51 * copying PR_ExplodeTime and PR_LocalTimeParameters. (The PR_ExplodeTime | 51 * copying PR_ExplodeTime and PR_LocalTimeParameters. (The PR_ExplodeTime |
52 * and PR_ImplodeTime calls cancel each other out.) | 52 * and PR_ImplodeTime calls cancel each other out.) |
53 * PR_NormalizeTime | 53 * PR_NormalizeTime |
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. |
wtc
2016/02/12 16:15:32
Please delete these two lines. They describe the o
pkl (ping after 24h if needed)
2016/02/15 18:07:15
Done.
| |
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 * | 64 * |
65 * Unit tests are in base/time/pr_time_unittest.cc. | 65 * Unit tests are in base/time/pr_time_unittest.cc. |
66 */ | 66 */ |
67 | 67 |
68 #include <limits.h> | 68 #include <limits.h> |
69 | 69 |
70 #include "base/logging.h" | 70 #include "base/logging.h" |
71 #include "base/third_party/nspr/prtime.h" | 71 #include "base/third_party/nspr/prtime.h" |
72 #include "build/build_config.h" | 72 #include "build/build_config.h" |
73 | 73 |
74 #if defined(OS_WIN) | |
75 #include <windows.h> | |
76 #elif defined(OS_MACOSX) | |
77 #include <CoreFoundation/CoreFoundation.h> | |
78 #elif defined(OS_ANDROID) | |
79 #include <ctype.h> | |
80 #include "base/os_compat_android.h" // For timegm() | |
81 #elif defined(OS_NACL) | |
82 #include "base/os_compat_nacl.h" // For timegm() | |
83 #endif | |
84 #include <errno.h> /* for EINVAL */ | 74 #include <errno.h> /* for EINVAL */ |
85 #include <time.h> | 75 #include <time.h> |
86 | 76 |
77 /* | |
78 * Long-long (64-bit signed integer type) support functions | |
wtc
2016/02/12 16:15:32
Nit: functions => macros
pkl (ping after 24h if needed)
2016/02/15 18:07:16
Done.
| |
79 * used by PR_ImplodeTime(). | |
80 * See http://lxr.mozilla.org/nspr/source/pr/include/prlong.h | |
81 */ | |
82 #define LL_I2L(l, i) ((l) = (PRInt64)(i)) | |
83 #define LL_MUL(r, a, b) ((r) = (a) * (b)) | |
84 #define LL_ADD(r, a, b) ((r) = (a) + (b)) | |
85 #define LL_SUB(r, a, b) ((r) = (a) - (b)) | |
wtc
2016/02/12 16:15:32
Optional: Based on the comment at lines 58-63, the
pkl (ping after 24h if needed)
2016/02/15 18:07:15
I would rather defer this move until a later time.
| |
86 | |
87 /* | |
88 * The COUNT_LEAPS macro counts the number of leap years passed by | |
89 * till the start of the given year Y. At the start of the year 4 | |
90 * A.D. the number of leap years passed by is 0, while at the start of | |
91 * the year 5 A.D. this count is 1. The number of years divisible by | |
92 * 100 but not divisible by 400 (the non-leap years) is deducted from | |
93 * the count to get the correct number of leap years. | |
94 * | |
95 * The COUNT_DAYS macro counts the number of days since 01/01/01 till the | |
96 * start of the given year Y. The number of days at the start of the year | |
97 * 1 is 0 while the number of days at the start of the year 2 is 365 | |
98 * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 | |
99 * midnight 00:00:00. | |
100 */ | |
101 | |
102 #define COUNT_LEAPS(Y) (((Y)-1) / 4 - ((Y)-1) / 100 + ((Y)-1) / 400) | |
103 #define COUNT_DAYS(Y) (((Y)-1) * 365 + COUNT_LEAPS(Y)) | |
104 #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) | |
105 | |
87 /* Implements the Unix localtime_r() function for windows */ | 106 /* Implements the Unix localtime_r() function for windows */ |
88 #if defined(OS_WIN) | 107 #if defined(OS_WIN) |
89 static void localtime_r(const time_t* secs, struct tm* time) { | 108 static void localtime_r(const time_t* secs, struct tm* time) { |
90 (void) localtime_s(time, secs); | 109 (void) localtime_s(time, secs); |
91 } | 110 } |
92 #endif | 111 #endif |
93 | 112 |
94 /* | 113 /* |
95 *------------------------------------------------------------------------ | 114 *------------------------------------------------------------------------ |
96 * | 115 * |
97 * PR_ImplodeTime -- | 116 * PR_ImplodeTime -- |
98 * | 117 * |
99 * Cf. time_t mktime(struct tm *tp) | 118 * Cf. time_t mktime(struct tm *tp) |
100 * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. | 119 * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. |
101 * | 120 * |
121 * Upstream implementation from | |
122 * http://lxr.mozilla.org/nspr/source/pr/src/misc/prtime.c#221 | |
wtc
2016/02/12 16:15:32
This note can be omitted or should be moved to the
pkl (ping after 24h if needed)
2016/02/15 18:07:15
I moved it to the beginning of the file (around li
| |
123 * | |
102 *------------------------------------------------------------------------ | 124 *------------------------------------------------------------------------ |
103 */ | 125 */ |
104 PRTime | 126 PRTime |
105 PR_ImplodeTime(const PRExplodedTime *exploded) | 127 PR_ImplodeTime(const PRExplodedTime *exploded) |
106 { | 128 { |
107 // This is important, we want to make sure multiplications are | 129 PRExplodedTime copy; |
108 // done with the correct precision. | 130 PRTime retVal; |
109 static const PRTime kSecondsToMicroseconds = static_cast<PRTime>(1000000); | 131 PRInt64 secPerDay, usecPerSec; |
110 #if defined(OS_WIN) | 132 PRInt64 temp; |
111 // Create the system struct representing our exploded time. | 133 PRInt64 numSecs64; |
112 SYSTEMTIME st = {}; | 134 PRInt32 numDays; |
113 FILETIME ft = {}; | 135 PRInt32 numSecs; |
114 ULARGE_INTEGER uli = {}; | |
115 | 136 |
116 st.wYear = exploded->tm_year; | 137 /* Normalize first. Do this on our copy */ |
117 st.wMonth = static_cast<WORD>(exploded->tm_month + 1); | 138 copy = *exploded; |
118 st.wDayOfWeek = exploded->tm_wday; | 139 PR_NormalizeTime(©, PR_GMTParameters); |
119 st.wDay = static_cast<WORD>(exploded->tm_mday); | |
120 st.wHour = static_cast<WORD>(exploded->tm_hour); | |
121 st.wMinute = static_cast<WORD>(exploded->tm_min); | |
122 st.wSecond = static_cast<WORD>(exploded->tm_sec); | |
123 st.wMilliseconds = static_cast<WORD>(exploded->tm_usec/1000); | |
124 // Convert to FILETIME. | |
125 if (!SystemTimeToFileTime(&st, &ft)) { | |
126 NOTREACHED() << "Unable to convert time"; | |
127 return 0; | |
128 } | |
129 // Apply offsets. | |
130 uli.LowPart = ft.dwLowDateTime; | |
131 uli.HighPart = ft.dwHighDateTime; | |
132 // Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units | |
133 // to microsecond units. | |
134 PRTime result = | |
135 static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64); | |
136 // Adjust for time zone and dst. Convert from seconds to microseconds. | |
137 result -= (exploded->tm_params.tp_gmt_offset + | |
138 exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds; | |
139 // Add microseconds that cannot be represented in |st|. | |
140 result += exploded->tm_usec % 1000; | |
141 return result; | |
142 #elif defined(OS_MACOSX) | |
143 // Create the system struct representing our exploded time. | |
144 CFGregorianDate gregorian_date; | |
145 gregorian_date.year = exploded->tm_year; | |
146 gregorian_date.month = exploded->tm_month + 1; | |
147 gregorian_date.day = exploded->tm_mday; | |
148 gregorian_date.hour = exploded->tm_hour; | |
149 gregorian_date.minute = exploded->tm_min; | |
150 gregorian_date.second = exploded->tm_sec; | |
151 | 140 |
152 // Compute |absolute_time| in seconds, correct for gmt and dst | 141 numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year); |
153 // (note the combined offset will be negative when we need to add it), then | |
154 // convert to microseconds which is what PRTime expects. | |
155 CFAbsoluteTime absolute_time = | |
156 CFGregorianDateGetAbsoluteTime(gregorian_date, NULL); | |
157 PRTime result = static_cast<PRTime>(absolute_time); | |
158 result -= exploded->tm_params.tp_gmt_offset + | |
159 exploded->tm_params.tp_dst_offset; | |
160 result += kCFAbsoluteTimeIntervalSince1970; // PRTime epoch is 1970 | |
161 result *= kSecondsToMicroseconds; | |
162 result += exploded->tm_usec; | |
163 return result; | |
164 #elif defined(OS_POSIX) | |
165 struct tm exp_tm = {0}; | |
166 exp_tm.tm_sec = exploded->tm_sec; | |
167 exp_tm.tm_min = exploded->tm_min; | |
168 exp_tm.tm_hour = exploded->tm_hour; | |
169 exp_tm.tm_mday = exploded->tm_mday; | |
170 exp_tm.tm_mon = exploded->tm_month; | |
171 exp_tm.tm_year = exploded->tm_year - 1900; | |
172 | 142 |
173 time_t absolute_time = timegm(&exp_tm); | 143 numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600 + copy.tm_min * 60 + |
144 copy.tm_sec; | |
174 | 145 |
175 // If timegm returned -1. Since we don't pass it a time zone, the only | 146 LL_I2L(temp, numDays); |
176 // valid case of returning -1 is 1 second before Epoch (Dec 31, 1969). | 147 LL_I2L(secPerDay, 86400); |
177 if (absolute_time == -1 && | 148 LL_MUL(temp, temp, secPerDay); |
178 !(exploded->tm_year == 1969 && exploded->tm_month == 11 && | 149 LL_I2L(numSecs64, numSecs); |
179 exploded->tm_mday == 31 && exploded->tm_hour == 23 && | 150 LL_ADD(numSecs64, numSecs64, temp); |
180 exploded->tm_min == 59 && exploded->tm_sec == 59)) { | |
181 // If we get here, time_t must be 32 bits. | |
182 // Date was possibly too far in the future and would overflow. Return | |
183 // the most future date possible (year 2038). | |
184 if (exploded->tm_year >= 1970) | |
185 return INT_MAX * kSecondsToMicroseconds; | |
186 // Date was possibly too far in the past and would underflow. Return | |
187 // the most past date possible (year 1901). | |
188 return INT_MIN * kSecondsToMicroseconds; | |
189 } | |
190 | 151 |
191 PRTime result = static_cast<PRTime>(absolute_time); | 152 /* apply the GMT and DST offsets */ |
192 result -= exploded->tm_params.tp_gmt_offset + | 153 LL_I2L(temp, copy.tm_params.tp_gmt_offset); |
193 exploded->tm_params.tp_dst_offset; | 154 LL_SUB(numSecs64, numSecs64, temp); |
194 result *= kSecondsToMicroseconds; | 155 LL_I2L(temp, copy.tm_params.tp_dst_offset); |
195 result += exploded->tm_usec; | 156 LL_SUB(numSecs64, numSecs64, temp); |
196 return result; | 157 |
197 #else | 158 LL_I2L(usecPerSec, 1000000L); |
198 #error No PR_ImplodeTime implemented on your platform. | 159 LL_MUL(temp, numSecs64, usecPerSec); |
199 #endif | 160 LL_I2L(retVal, copy.tm_usec); |
161 LL_ADD(retVal, retVal, temp); | |
162 | |
163 return retVal; | |
200 } | 164 } |
201 | 165 |
202 /* | |
203 * The COUNT_LEAPS macro counts the number of leap years passed by | |
204 * till the start of the given year Y. At the start of the year 4 | |
205 * A.D. the number of leap years passed by is 0, while at the start of | |
206 * the year 5 A.D. this count is 1. The number of years divisible by | |
207 * 100 but not divisible by 400 (the non-leap years) is deducted from | |
208 * the count to get the correct number of leap years. | |
209 * | |
210 * The COUNT_DAYS macro counts the number of days since 01/01/01 till the | |
211 * start of the given year Y. The number of days at the start of the year | |
212 * 1 is 0 while the number of days at the start of the year 2 is 365 | |
213 * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 | |
214 * midnight 00:00:00. | |
215 */ | |
216 | |
217 #define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) | |
218 #define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) | |
219 #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) | |
220 | |
221 /* | 166 /* |
222 * Static variables used by functions in this file | 167 * Static variables used by functions in this file |
223 */ | 168 */ |
224 | 169 |
225 /* | 170 /* |
226 * The following array contains the day of year for the last day of | 171 * The following array contains the day of year for the last day of |
227 * each month, where index 1 is January, and day 0 is January 1. | 172 * each month, where index 1 is January, and day 0 is January 1. |
228 */ | 173 */ |
229 | 174 |
230 static const int lastDayOfMonth[2][13] = { | 175 static const int lastDayOfMonth[2][13] = { |
231 {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, | 176 {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, |
232 {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} | 177 {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} |
233 }; | 178 }; |
234 | 179 |
235 /* | 180 /* |
236 * The number of days in a month | 181 * The number of days in a month |
237 */ | 182 */ |
238 | 183 |
239 static const PRInt8 nDays[2][12] = { | 184 static const PRInt8 nDays[2][12] = { |
240 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, | 185 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, |
241 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} | 186 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} |
242 }; | 187 }; |
243 | 188 |
wtc
2016/02/12 16:15:32
Nit/optional: To match the upstream source file cl
pkl (ping after 24h if needed)
2016/02/15 18:07:16
Done.
| |
244 /* | 189 /* |
245 *------------------------------------------------------------------------- | 190 *------------------------------------------------------------------------- |
246 * | 191 * |
247 * IsLeapYear -- | 192 * IsLeapYear -- |
248 * | 193 * |
249 * Returns 1 if the year is a leap year, 0 otherwise. | 194 * Returns 1 if the year is a leap year, 0 otherwise. |
250 * | 195 * |
251 *------------------------------------------------------------------------- | 196 *------------------------------------------------------------------------- |
252 */ | 197 */ |
253 | 198 |
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1245 + 60 * localTime.tm_hour | 1190 + 60 * localTime.tm_hour |
1246 + 1440 * (localTime.tm_mday - 2); | 1191 + 1440 * (localTime.tm_mday - 2); |
1247 } | 1192 } |
1248 | 1193 |
1249 result->tm_params.tp_gmt_offset = zone_offset * 60; | 1194 result->tm_params.tp_gmt_offset = zone_offset * 60; |
1250 result->tm_params.tp_dst_offset = dst_offset * 60; | 1195 result->tm_params.tp_dst_offset = dst_offset * 60; |
1251 | 1196 |
1252 *result_imploded = PR_ImplodeTime(result); | 1197 *result_imploded = PR_ImplodeTime(result); |
1253 return PR_SUCCESS; | 1198 return PR_SUCCESS; |
1254 } | 1199 } |
OLD | NEW |