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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 | 46 |
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 * Upstream implementation from |
57 * and the timezone offsets are applied to the FILETIME structure. | 57 * http://lxr.mozilla.org/nspr/source/pr/src/misc/prtime.c#221 |
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 |
87 /* Implements the Unix localtime_r() function for windows */ | 77 /* |
88 #if defined(OS_WIN) | 78 * Long-long (64-bit signed integer type) support macros used by |
89 static void localtime_r(const time_t* secs, struct tm* time) { | 79 * PR_ImplodeTime(). |
90 (void) localtime_s(time, secs); | 80 * See http://lxr.mozilla.org/nspr/source/pr/include/prlong.h |
91 } | 81 */ |
92 #endif | 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)) |
93 | 86 |
94 /* | 87 /* |
95 *------------------------------------------------------------------------ | |
96 * | |
97 * PR_ImplodeTime -- | |
98 * | |
99 * Cf. time_t mktime(struct tm *tp) | |
100 * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. | |
101 * | |
102 *------------------------------------------------------------------------ | |
103 */ | |
104 PRTime | |
105 PR_ImplodeTime(const PRExplodedTime *exploded) | |
106 { | |
107 // This is important, we want to make sure multiplications are | |
108 // done with the correct precision. | |
109 static const PRTime kSecondsToMicroseconds = static_cast<PRTime>(1000000); | |
110 #if defined(OS_WIN) | |
111 // Create the system struct representing our exploded time. | |
112 SYSTEMTIME st = {}; | |
113 FILETIME ft = {}; | |
114 ULARGE_INTEGER uli = {}; | |
115 | |
116 st.wYear = exploded->tm_year; | |
117 st.wMonth = static_cast<WORD>(exploded->tm_month + 1); | |
118 st.wDayOfWeek = exploded->tm_wday; | |
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 | |
152 // Compute |absolute_time| in seconds, correct for gmt and dst | |
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 | |
173 time_t absolute_time = timegm(&exp_tm); | |
174 | |
175 // If timegm returned -1. Since we don't pass it a time zone, the only | |
176 // valid case of returning -1 is 1 second before Epoch (Dec 31, 1969). | |
177 if (absolute_time == -1 && | |
178 !(exploded->tm_year == 1969 && exploded->tm_month == 11 && | |
179 exploded->tm_mday == 31 && exploded->tm_hour == 23 && | |
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 | |
191 PRTime result = static_cast<PRTime>(absolute_time); | |
192 result -= exploded->tm_params.tp_gmt_offset + | |
193 exploded->tm_params.tp_dst_offset; | |
194 result *= kSecondsToMicroseconds; | |
195 result += exploded->tm_usec; | |
196 return result; | |
197 #else | |
198 #error No PR_ImplodeTime implemented on your platform. | |
199 #endif | |
200 } | |
201 | |
202 /* | |
203 * The COUNT_LEAPS macro counts the number of leap years passed by | 88 * 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 | 89 * 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 | 90 * 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 | 91 * 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 | 92 * 100 but not divisible by 400 (the non-leap years) is deducted from |
208 * the count to get the correct number of leap years. | 93 * the count to get the correct number of leap years. |
209 * | 94 * |
210 * The COUNT_DAYS macro counts the number of days since 01/01/01 till the | 95 * 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 | 96 * 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 | 97 * 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 | 98 * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 |
214 * midnight 00:00:00. | 99 * midnight 00:00:00. |
215 */ | 100 */ |
216 | 101 |
217 #define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) | 102 #define COUNT_LEAPS(Y) (((Y)-1) / 4 - ((Y)-1) / 100 + ((Y)-1) / 400) |
218 #define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) | 103 #define COUNT_DAYS(Y) (((Y)-1) * 365 + COUNT_LEAPS(Y)) |
219 #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) | 104 #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) |
| 105 |
| 106 /* Implements the Unix localtime_r() function for windows */ |
| 107 #if defined(OS_WIN) |
| 108 static void localtime_r(const time_t* secs, struct tm* time) { |
| 109 (void) localtime_s(time, secs); |
| 110 } |
| 111 #endif |
220 | 112 |
221 /* | 113 /* |
222 * Static variables used by functions in this file | 114 * Static variables used by functions in this file |
223 */ | 115 */ |
224 | 116 |
225 /* | 117 /* |
226 * The following array contains the day of year for the last day of | 118 * 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. | 119 * each month, where index 1 is January, and day 0 is January 1. |
228 */ | 120 */ |
229 | 121 |
230 static const int lastDayOfMonth[2][13] = { | 122 static const int lastDayOfMonth[2][13] = { |
231 {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, | 123 {-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} | 124 {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} |
233 }; | 125 }; |
234 | 126 |
235 /* | 127 /* |
236 * The number of days in a month | 128 * The number of days in a month |
237 */ | 129 */ |
238 | 130 |
239 static const PRInt8 nDays[2][12] = { | 131 static const PRInt8 nDays[2][12] = { |
240 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, | 132 {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} | 133 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} |
242 }; | 134 }; |
243 | 135 |
244 /* | 136 /* |
| 137 *------------------------------------------------------------------------ |
| 138 * |
| 139 * PR_ImplodeTime -- |
| 140 * |
| 141 * Cf. time_t mktime(struct tm *tp) |
| 142 * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. |
| 143 * |
| 144 *------------------------------------------------------------------------ |
| 145 */ |
| 146 PRTime |
| 147 PR_ImplodeTime(const PRExplodedTime *exploded) |
| 148 { |
| 149 PRExplodedTime copy; |
| 150 PRTime retVal; |
| 151 PRInt64 secPerDay, usecPerSec; |
| 152 PRInt64 temp; |
| 153 PRInt64 numSecs64; |
| 154 PRInt32 numDays; |
| 155 PRInt32 numSecs; |
| 156 |
| 157 /* Normalize first. Do this on our copy */ |
| 158 copy = *exploded; |
| 159 PR_NormalizeTime(©, PR_GMTParameters); |
| 160 |
| 161 numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year); |
| 162 |
| 163 numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600 + copy.tm_min * 60 + |
| 164 copy.tm_sec; |
| 165 |
| 166 LL_I2L(temp, numDays); |
| 167 LL_I2L(secPerDay, 86400); |
| 168 LL_MUL(temp, temp, secPerDay); |
| 169 LL_I2L(numSecs64, numSecs); |
| 170 LL_ADD(numSecs64, numSecs64, temp); |
| 171 |
| 172 /* apply the GMT and DST offsets */ |
| 173 LL_I2L(temp, copy.tm_params.tp_gmt_offset); |
| 174 LL_SUB(numSecs64, numSecs64, temp); |
| 175 LL_I2L(temp, copy.tm_params.tp_dst_offset); |
| 176 LL_SUB(numSecs64, numSecs64, temp); |
| 177 |
| 178 LL_I2L(usecPerSec, 1000000L); |
| 179 LL_MUL(temp, numSecs64, usecPerSec); |
| 180 LL_I2L(retVal, copy.tm_usec); |
| 181 LL_ADD(retVal, retVal, temp); |
| 182 |
| 183 return retVal; |
| 184 } |
| 185 |
| 186 /* |
245 *------------------------------------------------------------------------- | 187 *------------------------------------------------------------------------- |
246 * | 188 * |
247 * IsLeapYear -- | 189 * IsLeapYear -- |
248 * | 190 * |
249 * Returns 1 if the year is a leap year, 0 otherwise. | 191 * Returns 1 if the year is a leap year, 0 otherwise. |
250 * | 192 * |
251 *------------------------------------------------------------------------- | 193 *------------------------------------------------------------------------- |
252 */ | 194 */ |
253 | 195 |
254 static int IsLeapYear(PRInt16 year) | 196 static int IsLeapYear(PRInt16 year) |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 + 60 * localTime.tm_hour | 1187 + 60 * localTime.tm_hour |
1246 + 1440 * (localTime.tm_mday - 2); | 1188 + 1440 * (localTime.tm_mday - 2); |
1247 } | 1189 } |
1248 | 1190 |
1249 result->tm_params.tp_gmt_offset = zone_offset * 60; | 1191 result->tm_params.tp_gmt_offset = zone_offset * 60; |
1250 result->tm_params.tp_dst_offset = dst_offset * 60; | 1192 result->tm_params.tp_dst_offset = dst_offset * 60; |
1251 | 1193 |
1252 *result_imploded = PR_ImplodeTime(result); | 1194 *result_imploded = PR_ImplodeTime(result); |
1253 return PR_SUCCESS; | 1195 return PR_SUCCESS; |
1254 } | 1196 } |
OLD | NEW |