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

Unified Diff: runtime/lib/date.cc

Issue 10359003: Reapply "Set the TZ env to get the UTC-ms since epoch." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix warning. Created 8 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/os.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/date.cc
diff --git a/runtime/lib/date.cc b/runtime/lib/date.cc
index 9a993428627f1649eb3abb23b9f4f31b35ce8dfd..90158c9a345475fcf072595be66597ccd2079842 100644
--- a/runtime/lib/date.cc
+++ b/runtime/lib/date.cc
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include <time.h>
+
#include "vm/bootstrap_natives.h"
#include "vm/bigint_operations.h"
@@ -11,13 +13,98 @@
namespace dart {
+typedef struct BrokenDownDate {
+ intptr_t year;
+ intptr_t month; // [1..12]
+ intptr_t day; // [1..31]
+ intptr_t hours;
+ intptr_t minutes;
+ intptr_t seconds;
+} BrokenDownDate;
+
+
+// Takes the seconds since epoch (midnight, January 1, 1970 UTC) and breaks it
+// down into date and time.
+// If 'dart_is_utc', then the broken down date and time are in the UTC timezone,
+// otherwise the local timezone is used.
+// The returned year is offset by 1900. The returned month is 0-based.
+// Returns true if the conversion succeeds, false otherwise.
static bool BreakDownSecondsSinceEpoch(const Integer& dart_seconds,
const Bool& dart_is_utc,
- OS::BrokenDownDate* result) {
+ BrokenDownDate* result) {
+ // Always fill the result to avoid unitialized use warnings.
+ result->year = 0;
+ result->month = 0;
+ result->day = 0;
+ result->hours = 0;
+ result->minutes = 0;
+ result->seconds = 0;
+
bool is_utc = dart_is_utc.value();
- int64_t value = dart_seconds.AsInt64Value();
- time_t seconds = static_cast<time_t>(value);
- return OS::BreakDownSecondsSinceEpoch(seconds, is_utc, result);
+ int64_t seconds = dart_seconds.AsInt64Value();
+
+ struct tm tm_result;
+ bool succeeded;
+ if (is_utc) {
+ succeeded = OS::GmTime(seconds, &tm_result);
+ } else {
+ succeeded = OS::LocalTime(seconds, &tm_result);
+ }
+ if (succeeded) {
+ result->year = tm_result.tm_year;
+ // C uses years since 1900, and not full years.
+ // Adding 1900 could overflow the intptr_t.
+ if (result->year > kIntptrMax - 1900) return false;
+ result->year += 1900;
+ // Dart has 1-based months (contrary to C's 0-based).
+ result->month= tm_result.tm_mon + 1;
+ result->day = tm_result.tm_mday;
+ result->hours = tm_result.tm_hour;
+ result->minutes = tm_result.tm_min;
+ result->seconds = tm_result.tm_sec;
+ }
+ return succeeded;
+}
+
+
+static bool BrokenDownToSecondsSinceEpoch(const BrokenDownDate& broken_down,
+ bool in_utc,
+ int64_t* result) {
+ // Always set the result to avoid unitialized use warnings.
+ *result = 0;
+
+ struct tm tm_broken_down;
+ intptr_t year = broken_down.year;
+ // C works with years since 1900.
+ // Removing 1900 could underflow the intptr_t.
+ if (year < kIntptrMin + 1900) return false;
+ year -= 1900;
+ intptr_t month = broken_down.month;
+ // C works with 0-based months.
+ // Avoid underflows (even though they should not matter since the date would
+ // be invalid anyways.
+ if (month < 0) return false;
+ month--;
+ tm_broken_down.tm_year = static_cast<int>(year);
+ tm_broken_down.tm_mon = static_cast<int>(month);
+ tm_broken_down.tm_mday = static_cast<int>(broken_down.day);
+ tm_broken_down.tm_hour = static_cast<int>(broken_down.hours);
+ tm_broken_down.tm_min = static_cast<int>(broken_down.minutes);
+ tm_broken_down.tm_sec = static_cast<int>(broken_down.seconds);
+ // Verify that casting to int did not change the value.
+ if (tm_broken_down.tm_year != year
+ || tm_broken_down.tm_mon != month
+ || tm_broken_down.tm_mday != broken_down.day
+ || tm_broken_down.tm_hour != broken_down.hours
+ || tm_broken_down.tm_min != broken_down.minutes
+ || tm_broken_down.tm_sec != broken_down.seconds) {
+ return false;
+ }
+ if (in_utc) {
+ return OS::MkGmTime(&tm_broken_down, result);
+ } else {
+ return OS::MkTime(&tm_broken_down, result);
+ }
}
@@ -34,24 +121,17 @@ DEFINE_NATIVE_ENTRY(DateNatives_brokenDownToSecondsSinceEpoch, 7) {
}
Smi& smi_years = Smi::Handle();
smi_years ^= dart_years.raw();
- OS::BrokenDownDate broken_down;
- // mktime takes the years since 1900.
- // TODO(floitsch): Removing 1900 could underflow the intptr_t.
- intptr_t year = smi_years.Value() - 1900;
- // TODO(1143): We don't handle the case yet where intptr_t and int have
- // different sizes.
- // ASSERT(sizeof(year) <= sizeof(broken_down.year));
- broken_down.year = static_cast<int>(year);
- // libc months are 0-based (contrary to Dart' 1-based months).
- broken_down.month = dart_month.Value() - 1;
+ BrokenDownDate broken_down;
+ broken_down.year = smi_years.Value();
+ broken_down.month = dart_month.Value();
broken_down.day = dart_day.Value();
broken_down.hours = dart_hours.Value();
broken_down.minutes = dart_minutes.Value();
broken_down.seconds = dart_seconds.Value();
- time_t value;
- bool succeeded = OS::BrokenDownToSecondsSinceEpoch(broken_down,
- dart_is_utc.value(),
- &value);
+ int64_t value;
+ bool succeeded = BrokenDownToSecondsSinceEpoch(broken_down,
+ dart_is_utc.value(),
+ &value);
if (!succeeded) {
UNIMPLEMENTED();
}
@@ -69,15 +149,13 @@ DEFINE_NATIVE_ENTRY(DateNatives_currentTimeMillis, 0) {
DEFINE_NATIVE_ENTRY(DateNatives_getYear, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
UNIMPLEMENTED();
}
- // C uses years since 1900, and not full years.
- // TODO(floitsch): adding 1900 could overflow the intptr_t.
- intptr_t year = broken_down.year + 1900;
+ intptr_t year = broken_down.year;
arguments->SetReturn(Integer::Handle(Integer::New(year)));
}
@@ -85,14 +163,13 @@ DEFINE_NATIVE_ENTRY(DateNatives_getYear, 2) {
DEFINE_NATIVE_ENTRY(DateNatives_getMonth, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
UNIMPLEMENTED();
}
- // Dart has 1-based months (contrary to C's 0-based).
- const Smi& result = Smi::Handle(Smi::New(broken_down.month + 1));
+ const Smi& result = Smi::Handle(Smi::New(broken_down.month));
arguments->SetReturn(result);
}
@@ -100,7 +177,7 @@ DEFINE_NATIVE_ENTRY(DateNatives_getMonth, 2) {
DEFINE_NATIVE_ENTRY(DateNatives_getDay, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
@@ -114,7 +191,7 @@ DEFINE_NATIVE_ENTRY(DateNatives_getDay, 2) {
DEFINE_NATIVE_ENTRY(DateNatives_getHours, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
@@ -128,7 +205,7 @@ DEFINE_NATIVE_ENTRY(DateNatives_getHours, 2) {
DEFINE_NATIVE_ENTRY(DateNatives_getMinutes, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
@@ -142,7 +219,7 @@ DEFINE_NATIVE_ENTRY(DateNatives_getMinutes, 2) {
DEFINE_NATIVE_ENTRY(DateNatives_getSeconds, 2) {
GET_NATIVE_ARGUMENT(Integer, dart_seconds, arguments->At(0));
GET_NATIVE_ARGUMENT(Bool, dart_is_utc, arguments->At(1));
- OS::BrokenDownDate broken_down;
+ BrokenDownDate broken_down;
bool succeeded =
BreakDownSecondsSinceEpoch(dart_seconds, dart_is_utc, &broken_down);
if (!succeeded) {
« no previous file with comments | « no previous file | runtime/vm/os.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698