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

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

Issue 1657433002: Use upstream version of PR_ImplodeTime (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressed comments from wtc Created 4 years, 10 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
« no previous file with comments | « no previous file | 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 /* 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
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(&copy, 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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698