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

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: comment attributing source 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(&copy, 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
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 }
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