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

Side by Side Diff: base/time/time_posix.cc

Issue 1988663002: Add: check exploded time is properly converted (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/time/time.h" 5 #include "base/time/time.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <sys/time.h> 8 #include <sys/time.h>
9 #include <time.h> 9 #include <time.h>
10 #if defined(OS_ANDROID) && !defined(__LP64__) 10 #if defined(OS_ANDROID) && !defined(__LP64__)
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 milliseconds = min_seconds * kMillisecondsPerSecond; 294 milliseconds = min_seconds * kMillisecondsPerSecond;
295 } else { 295 } else {
296 milliseconds = max_seconds * kMillisecondsPerSecond; 296 milliseconds = max_seconds * kMillisecondsPerSecond;
297 milliseconds += (kMillisecondsPerSecond - 1); 297 milliseconds += (kMillisecondsPerSecond - 1);
298 } 298 }
299 } else { 299 } else {
300 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; 300 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond;
301 } 301 }
302 302
303 // Adjust from Unix (1970) to Windows (1601) epoch. 303 // Adjust from Unix (1970) to Windows (1601) epoch.
304 return Time((milliseconds * kMicrosecondsPerMillisecond) + 304 base::Time t_time = Time((milliseconds * kMicrosecondsPerMillisecond) +
305 kWindowsEpochDeltaMicroseconds); 305 kWindowsEpochDeltaMicroseconds);
mmenke 2016/05/20 19:44:57 Again, suggest just calling this |time|, unless th
maksims (do not use this acc) 2016/05/24 09:14:21 Done.
306 // If |exploded.day_of_month| is set to 31
307 // on a 28-30 day month, it will return the first day of the next month.
308 // Thus round-trip the time and compare the initial |exploded| with
309 // |utc_to_exploded| time.
310 base::Time::Exploded to_exploded;
311 if (!is_local)
312 t_time.UTCExplode(&to_exploded);
313 else
314 t_time.LocalExplode(&to_exploded);
315
316 // If time is null, return false
317 // which means time conversion failed
318 return to_exploded != exploded ? Time(0) : t_time;
mmenke 2016/05/20 19:44:57 nit: Fix indent. You can automatically format ev
maksims (do not use this acc) 2016/05/24 09:14:21 Done.
319 }
320
321 // static
322 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time& time) {
323 struct tm timestruct;
324 timestruct.tm_sec = exploded.second;
325 timestruct.tm_min = exploded.minute;
326 timestruct.tm_hour = exploded.hour;
327 timestruct.tm_mday = exploded.day_of_month;
328 timestruct.tm_mon = exploded.month - 1;
329 timestruct.tm_year = exploded.year - 1900;
330 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this
331 timestruct.tm_yday = 0; // mktime/timegm ignore this
332 timestruct.tm_isdst = -1; // attempt to figure it out
333 #if !defined(OS_NACL) && !defined(OS_SOLARIS)
334 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore
335 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore
336 #endif
337
338 int64_t milliseconds;
339 SysTime seconds;
340
341 // Certain exploded dates do not really exist due to daylight saving times,
342 // and this causes mktime() to return implementation-defined values when
343 // tm_isdst is set to -1. On Android, the function will return -1, while the
344 // C libraries of other platforms typically return a liberally-chosen value.
345 // Handling this requires the special code below.
346
347 // SysTimeFromTimeStruct() modifies the input structure, save current value.
348 struct tm timestruct0 = timestruct;
349
350 seconds = SysTimeFromTimeStruct(&timestruct, is_local);
351 if (seconds == -1) {
352 // Get the time values with tm_isdst == 0 and 1, then select the closest one
353 // to UTC 00:00:00 that isn't -1.
354 timestruct = timestruct0;
355 timestruct.tm_isdst = 0;
356 int64_t seconds_isdst0 = SysTimeFromTimeStruct(&timestruct, is_local);
357
358 timestruct = timestruct0;
359 timestruct.tm_isdst = 1;
360 int64_t seconds_isdst1 = SysTimeFromTimeStruct(&timestruct, is_local);
361
362 // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones.
363 // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'.
364 if (seconds_isdst0 < 0)
365 seconds = seconds_isdst1;
366 else if (seconds_isdst1 < 0)
367 seconds = seconds_isdst0;
368 else
369 seconds = std::min(seconds_isdst0, seconds_isdst1);
370 }
371
372 // Handle overflow. Clamping the range to what mktime and timegm might
373 // return is the best that can be done here. It's not ideal, but it's better
374 // than failing here or ignoring the overflow case and treating each time
375 // overflow as one second prior to the epoch.
376 if (seconds == -1 &&
377 (exploded.year < 1969 || exploded.year > 1970)) {
378 // If exploded.year is 1969 or 1970, take -1 as correct, with the
379 // time indicating 1 second prior to the epoch. (1970 is allowed to handle
380 // time zone and DST offsets.) Otherwise, return the most future or past
381 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC.
382 //
383 // The minimum and maximum representible times that mktime and timegm could
384 // return are used here instead of values outside that range to allow for
385 // proper round-tripping between exploded and counter-type time
386 // representations in the presence of possible truncation to time_t by
387 // division and use with other functions that accept time_t.
388 //
389 // When representing the most distant time in the future, add in an extra
390 // 999ms to avoid the time being less than any other possible value that
391 // this function can return.
392
393 // On Android, SysTime is int64_t, special care must be taken to avoid
394 // overflows.
395 const int64_t min_seconds = (sizeof(SysTime) < sizeof(int64_t))
396 ? std::numeric_limits<SysTime>::min()
397 : std::numeric_limits<int32_t>::min();
398 const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t))
399 ? std::numeric_limits<SysTime>::max()
400 : std::numeric_limits<int32_t>::max();
401 if (exploded.year < 1969) {
402 milliseconds = min_seconds * kMillisecondsPerSecond;
403 } else {
404 milliseconds = max_seconds * kMillisecondsPerSecond;
405 milliseconds += (kMillisecondsPerSecond - 1);
406 }
407 } else {
408 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond;
409 }
410
411 // Adjust from Unix (1970) to Windows (1601) epoch.
412 base::Time t_time = Time((milliseconds * kMicrosecondsPerMillisecond) +
413 kWindowsEpochDeltaMicroseconds);
414 // If |exploded.day_of_month| is set to 31
415 // on a 28-30 day month, it will return the first day of the next month.
416 // Thus round-trip the time and compare the initial |exploded| with
417 // |utc_to_exploded| time.
418 base::Time::Exploded to_exploded;
419 if (!is_local)
420 t_time.UTCExplode(&to_exploded);
421 else
422 t_time.LocalExplode(&to_exploded);
423
424 time = to_exploded != exploded ? Time(0) : t_time;
425
426 // If time is null, return false
427 // which means time conversion failed
428 return time.is_null() ? false : true;
306 } 429 }
307 430
308 // TimeTicks ------------------------------------------------------------------ 431 // TimeTicks ------------------------------------------------------------------
309 // static 432 // static
310 TimeTicks TimeTicks::Now() { 433 TimeTicks TimeTicks::Now() {
311 return TimeTicks(ClockNow(CLOCK_MONOTONIC)); 434 return TimeTicks(ClockNow(CLOCK_MONOTONIC));
312 } 435 }
313 436
314 // static 437 // static
315 TimeTicks::Clock TimeTicks::GetClock() { 438 TimeTicks::Clock TimeTicks::GetClock() {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; 482 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
360 return result; 483 return result;
361 } 484 }
362 int64_t us = us_ - kTimeTToMicrosecondsOffset; 485 int64_t us = us_ - kTimeTToMicrosecondsOffset;
363 result.tv_sec = us / Time::kMicrosecondsPerSecond; 486 result.tv_sec = us / Time::kMicrosecondsPerSecond;
364 result.tv_usec = us % Time::kMicrosecondsPerSecond; 487 result.tv_usec = us % Time::kMicrosecondsPerSecond;
365 return result; 488 return result;
366 } 489 }
367 490
368 } // namespace base 491 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698