Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // Dart core library. | 4 // Dart core library. |
| 5 | 5 |
| 6 class TimeZoneImplementation implements TimeZone { | 6 class TimeZoneImplementation implements TimeZone { |
| 7 const TimeZoneImplementation.utc() : isUtc = true; | 7 const TimeZoneImplementation.utc() : isUtc = true; |
| 8 TimeZoneImplementation.local() : isUtc = false {} | 8 TimeZoneImplementation.local() : isUtc = false {} |
| 9 | 9 |
| 10 bool operator ==(Object other) { | 10 bool operator ==(Object other) { |
| 11 if (!(other is TimeZoneImplementation)) return false; | 11 if (!(other is TimeZoneImplementation)) return false; |
| 12 return isUtc == other.isUtc; | 12 return isUtc == other.isUtc; |
| 13 } | 13 } |
| 14 | 14 |
| 15 final bool isUtc; | 15 final bool isUtc; |
| 16 } | 16 } |
| 17 | 17 |
| 18 // JavaScript implementation of DateImplementation. | 18 // JavaScript implementation of DateImplementation. |
|
Mads Ager (google)
2012/05/22 09:11:22
JavaScript? Not your code, but could you update? :
floitsch
2012/05/22 14:50:38
It probably is my code :)
done.
| |
| 19 class DateImplementation implements Date { | 19 class DateImplementation implements Date { |
| 20 factory DateImplementation(int years, | 20 final bool _isUtcField; |
|
Mads Ager (google)
2012/05/22 09:11:22
You should move the instance fields to the end of
floitsch
2012/05/22 14:50:38
Done.
| |
| 21 [int month = 1, | 21 final int value; |
| 22 int day = 1, | 22 |
| 23 int hours = 0, | 23 static final int _SECONDS_YEAR_2035 = 2051222400; |
| 24 int minutes = 0, | 24 |
| 25 int seconds = 0, | 25 DateImplementation(int years, |
| 26 int milliseconds = 0]) { | 26 [int month = 1, |
| 27 return new DateImplementation.withTimeZone( | 27 int day = 1, |
| 28 years, month, day, | 28 int hours = 0, |
| 29 hours, minutes, seconds, milliseconds, | 29 int minutes = 0, |
| 30 new TimeZoneImplementation.local()); | 30 int seconds = 0, |
| 31 int milliseconds = 0, | |
| 32 bool isUtc = false]) | |
| 33 : _isUtcField = isUtc, | |
| 34 value = _brokenDownDateToMillisecondsSinceEpoch( | |
| 35 years, month, day, hours, minutes, seconds, milliseconds, isUtc) { | |
| 36 if (value === null) throw new IllegalArgumentException(); | |
| 31 } | 37 } |
| 32 | 38 |
| 33 DateImplementation.withTimeZone(int years, | 39 DateImplementation.withTimeZone(int years, |
| 34 int month, | 40 int month, |
| 35 int day, | 41 int day, |
| 36 int hours, | 42 int hours, |
| 37 int minutes, | 43 int minutes, |
| 38 int seconds, | 44 int seconds, |
| 39 int milliseconds, | 45 int milliseconds, |
| 40 TimeZone timeZone) | 46 TimeZone timeZone) |
| 41 : timeZone = timeZone, | 47 : this(years, month, day, hours, minutes, seconds, milliseconds, |
|
Mads Ager (google)
2012/05/22 09:11:22
four-space indent as above. Not your code, but cou
floitsch
2012/05/22 14:50:38
Done.
| |
| 42 value = _brokenDownDateToMillisecondsSinceEpoch( | 48 timeZone.isUtc); |
| 43 years, month, day, hours, minutes, seconds, milliseconds, | |
| 44 timeZone.isUtc) { | |
| 45 if (value === null) throw new IllegalArgumentException(); | |
| 46 } | |
| 47 | 49 |
| 48 DateImplementation.now() | 50 DateImplementation.now() |
| 49 : timeZone = new TimeZone.local(), | 51 : _isUtcField = true, |
|
Mads Ager (google)
2012/05/22 09:11:22
Ditto.
floitsch
2012/05/22 14:50:38
Done.
| |
| 50 value = _getCurrentMs() { | 52 value = _getCurrentMs() { |
| 51 } | 53 } |
| 52 | 54 |
| 53 factory DateImplementation.fromString(String formattedString) { | 55 factory DateImplementation.fromString(String formattedString) { |
| 54 // Read in (a subset of) ISO 8601. | 56 // Read in (a subset of) ISO 8601. |
| 55 // Examples: | 57 // Examples: |
| 56 // - "2012-02-27 13:27:00" | 58 // - "2012-02-27 13:27:00" |
| 57 // - "2012-02-27 13:27:00.423z" | 59 // - "2012-02-27 13:27:00.423z" |
| 58 // - "20120227 13:27:00" | 60 // - "20120227 13:27:00" |
| 59 // - "20120227T132700" | 61 // - "20120227T132700" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 84 int minutes = parseIntOrZero(match[5]); | 86 int minutes = parseIntOrZero(match[5]); |
| 85 int seconds = parseIntOrZero(match[6]); | 87 int seconds = parseIntOrZero(match[6]); |
| 86 bool addOneMillisecond = false; | 88 bool addOneMillisecond = false; |
| 87 int milliseconds = (parseDoubleOrZero(match[7]) * 1000).round().toInt(); | 89 int milliseconds = (parseDoubleOrZero(match[7]) * 1000).round().toInt(); |
| 88 if (milliseconds == 1000) { | 90 if (milliseconds == 1000) { |
| 89 addOneMillisecond = true; | 91 addOneMillisecond = true; |
| 90 milliseconds = 999; | 92 milliseconds = 999; |
| 91 } | 93 } |
| 92 // TODO(floitsch): we should not need to test against the empty string. | 94 // TODO(floitsch): we should not need to test against the empty string. |
| 93 bool isUtc = (match[8] !== null) && (match[8] != ""); | 95 bool isUtc = (match[8] !== null) && (match[8] != ""); |
| 94 TimeZone timezone = isUtc ? const TimeZone.utc() : new TimeZone.local(); | |
| 95 int epochValue = _brokenDownDateToMillisecondsSinceEpoch( | 96 int epochValue = _brokenDownDateToMillisecondsSinceEpoch( |
| 96 years, month, day, hours, minutes, seconds, milliseconds, isUtc); | 97 years, month, day, hours, minutes, seconds, milliseconds, isUtc); |
| 97 if (epochValue === null) { | 98 if (epochValue === null) { |
| 98 throw new IllegalArgumentException(formattedString); | 99 throw new IllegalArgumentException(formattedString); |
| 99 } | 100 } |
| 100 if (addOneMillisecond) epochValue++; | 101 if (addOneMillisecond) epochValue++; |
| 101 return new DateImplementation.fromEpoch(epochValue, timezone); | 102 return new DateImplementation.fromEpoch(epochValue, isUtc); |
| 102 } else { | 103 } else { |
| 103 throw new IllegalArgumentException(formattedString); | 104 throw new IllegalArgumentException(formattedString); |
| 104 } | 105 } |
| 105 } | 106 } |
| 106 | 107 |
| 107 const DateImplementation.fromEpoch(int this.value, | 108 DateImplementation.fromEpoch(int this.value, [bool isUtc = false]) |
| 108 TimeZone this.timeZone); | 109 : _isUtcField = isUtc; |
| 109 | 110 |
| 110 bool operator ==(Object other) { | 111 bool operator ==(Object other) { |
| 111 if (!(other is DateImplementation)) return false; | 112 if (!(other is DateImplementation)) return false; |
|
ngeoffray
2012/05/22 08:58:45
other is !
floitsch
2012/05/22 14:50:38
Done.
| |
| 112 return value == other.value && timeZone == other.timeZone; | 113 return value == other.value; |
| 113 } | 114 } |
| 114 | 115 |
| 115 bool operator <(Date other) => value < other.value; | 116 bool operator <(Date other) => value < other.value; |
| 116 | 117 |
| 117 bool operator <=(Date other) => value <= other.value; | 118 bool operator <=(Date other) => value <= other.value; |
| 118 | 119 |
| 119 bool operator >(Date other) => value > other.value; | 120 bool operator >(Date other) => value > other.value; |
| 120 | 121 |
| 121 bool operator >=(Date other) => value >= other.value; | 122 bool operator >=(Date other) => value >= other.value; |
| 122 | 123 |
| 123 int compareTo(Date other) => value.compareTo(other.value); | 124 int compareTo(Date other) => value.compareTo(other.value); |
| 124 int hashCode() => value; | 125 int hashCode() => value; |
| 125 | 126 |
| 127 Date toLocal() { | |
| 128 if (isUtc()) return new DateImplementation.fromEpoch(value, false); | |
| 129 return this; | |
| 130 } | |
| 131 | |
| 132 Date toUtc() { | |
| 133 if (isUtc()) return this; | |
| 134 return new DateImplementation.fromEpoch(value, true); | |
| 135 } | |
| 136 | |
| 126 Date changeTimeZone(TimeZone targetTimeZone) { | 137 Date changeTimeZone(TimeZone targetTimeZone) { |
| 127 if (targetTimeZone === null) { | 138 if (targetTimeZone === null) { |
| 128 targetTimeZone = new TimeZoneImplementation.local(); | 139 targetTimeZone = new TimeZoneImplementation.local(); |
| 129 } | 140 } |
| 130 return new Date.fromEpoch(value, targetTimeZone); | 141 return new Date.fromEpoch(value, targetTimeZone.isUtc); |
| 131 } | 142 } |
| 132 | 143 |
| 133 String get timeZoneName() { | 144 String get timeZoneName() { |
| 134 if (isUtc()) return "UTC"; | 145 if (isUtc()) return "UTC"; |
| 135 return _timeZoneName(_equivalentSeconds(_secondsSinceEpoch)); | 146 return _timeZoneName(_equivalentSeconds(_secondsSinceEpoch)); |
| 136 } | 147 } |
| 137 | 148 |
| 138 Duration get timeZoneOffset() { | 149 Duration get timeZoneOffset() { |
| 139 if (isUtc()) return new Duration(0); | 150 if (isUtc()) return new Duration(0); |
| 140 int offsetInSeconds = | 151 int offsetInSeconds = |
| 141 _timeZoneOffsetInSeconds(_equivalentSeconds(_secondsSinceEpoch)); | 152 _timeZoneOffsetInSeconds(_equivalentSeconds(_secondsSinceEpoch)); |
| 142 return new Duration(seconds: offsetInSeconds); | 153 return new Duration(seconds: offsetInSeconds); |
| 143 } | 154 } |
| 144 | 155 |
| 145 int get year() { | 156 int get year() { |
| 146 int secondsSinceEpoch = _secondsSinceEpoch; | 157 int secondsSinceEpoch = _secondsSinceEpoch; |
| 147 // According to V8 some library calls have troubles with negative values. | 158 // According to V8 some library calls have troubles with negative values. |
| 148 // Therefore clamp to 0 - year 2035 (which is less than the size of 32bit). | 159 // Therefore clamp to 0 - year 2035 (which is less than the size of 32bit). |
| 149 if (secondsSinceEpoch >= 0 && secondsSinceEpoch < _SECONDS_YEAR_2035) { | 160 if (secondsSinceEpoch >= 0 && secondsSinceEpoch < _SECONDS_YEAR_2035) { |
| 150 return _getYear(secondsSinceEpoch, timeZone.isUtc); | 161 return _getYear(secondsSinceEpoch, isUtc()); |
| 151 } | 162 } |
| 152 | 163 |
| 153 // Approximate the result. We don't take timeZone into account. | 164 // Approximate the result. We don't take timeZone into account. |
| 154 int approximateYear = _yearsFromSecondsSinceEpoch(secondsSinceEpoch); | 165 int approximateYear = _yearsFromSecondsSinceEpoch(secondsSinceEpoch); |
| 155 int equivalentYear = _equivalentYear(approximateYear); | 166 int equivalentYear = _equivalentYear(approximateYear); |
| 156 int y = _getYear(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 167 int y = _getYear(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 157 return approximateYear + (y - equivalentYear); | 168 return approximateYear + (y - equivalentYear); |
| 158 } | 169 } |
| 159 | 170 |
| 160 int get month() { | 171 int get month() { |
| 161 return _getMonth(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 172 return _getMonth(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 162 } | 173 } |
| 163 | 174 |
| 164 int get day() { | 175 int get day() { |
| 165 return _getDay(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 176 return _getDay(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 166 } | 177 } |
| 167 | 178 |
| 168 int get hours() { | 179 int get hours() { |
| 169 return _getHours(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 180 return _getHours(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 170 } | 181 } |
| 171 | 182 |
| 172 int get minutes() { | 183 int get minutes() { |
| 173 return _getMinutes(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 184 return _getMinutes(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 174 } | 185 } |
| 175 | 186 |
| 176 int get seconds() { | 187 int get seconds() { |
| 177 return _getSeconds(_equivalentSeconds(_secondsSinceEpoch), timeZone.isUtc); | 188 return _getSeconds(_equivalentSeconds(_secondsSinceEpoch), isUtc()); |
| 178 } | 189 } |
| 179 | 190 |
| 180 int get milliseconds() { | 191 int get milliseconds() { |
| 181 return value % Duration.MILLISECONDS_PER_SECOND; | 192 return value % Duration.MILLISECONDS_PER_SECOND; |
| 182 } | 193 } |
| 183 | 194 |
| 184 int get _secondsSinceEpoch() { | 195 int get _secondsSinceEpoch() { |
| 185 // Always round down. | 196 // Always round down. |
| 186 if (value < 0) { | 197 if (value < 0) { |
| 187 return (value + 1) ~/ Duration.MILLISECONDS_PER_SECOND - 1; | 198 return (value + 1) ~/ Duration.MILLISECONDS_PER_SECOND - 1; |
| 188 } else { | 199 } else { |
| 189 return value ~/ Duration.MILLISECONDS_PER_SECOND; | 200 return value ~/ Duration.MILLISECONDS_PER_SECOND; |
| 190 } | 201 } |
| 191 } | 202 } |
| 192 | 203 |
| 193 int get weekday() { | 204 int get weekday() { |
| 194 final Date unixTimeStart = | 205 final Date unixTimeStart = new Date(1970, 1, 1, 0, 0, 0, 0, isUtc()); |
| 195 new Date.withTimeZone(1970, 1, 1, 0, 0, 0, 0, timeZone); | |
| 196 int msSince1970 = this.difference(unixTimeStart).inMilliseconds; | 206 int msSince1970 = this.difference(unixTimeStart).inMilliseconds; |
| 197 // Adjust the milliseconds to avoid problems with summer-time. | 207 // Adjust the milliseconds to avoid problems with summer-time. |
| 198 if (hours < 2) { | 208 if (hours < 2) { |
| 199 msSince1970 += 2 * Duration.MILLISECONDS_PER_HOUR; | 209 msSince1970 += 2 * Duration.MILLISECONDS_PER_HOUR; |
| 200 } | 210 } |
| 201 // Compute the floor of msSince1970 / Duration.MS_PER_DAY. | 211 // Compute the floor of msSince1970 / Duration.MS_PER_DAY. |
| 202 int daysSince1970; | 212 int daysSince1970; |
| 203 if (msSince1970 >= 0) { | 213 if (msSince1970 >= 0) { |
| 204 daysSince1970 = msSince1970 ~/ Duration.MILLISECONDS_PER_DAY; | 214 daysSince1970 = msSince1970 ~/ Duration.MILLISECONDS_PER_DAY; |
| 205 } else { | 215 } else { |
| 206 daysSince1970 = (msSince1970 - Duration.MILLISECONDS_PER_DAY + 1) ~/ | 216 daysSince1970 = (msSince1970 - Duration.MILLISECONDS_PER_DAY + 1) ~/ |
| 207 Duration.MILLISECONDS_PER_DAY; | 217 Duration.MILLISECONDS_PER_DAY; |
| 208 } | 218 } |
| 209 // 1970-1-1 was a Thursday. | 219 // 1970-1-1 was a Thursday. |
| 210 return ((daysSince1970 + Date.THU) % Date.DAYS_IN_WEEK); | 220 return ((daysSince1970 + Date.THU) % Date.DAYS_IN_WEEK); |
| 211 } | 221 } |
| 212 | 222 |
| 213 bool isLocalTime() { | 223 bool isUtc() => _isUtcField; |
| 214 return !timeZone.isUtc; | |
| 215 } | |
| 216 | |
| 217 bool isUtc() { | |
| 218 return timeZone.isUtc; | |
| 219 } | |
| 220 | 224 |
| 221 String toString() { | 225 String toString() { |
| 222 String fourDigits(int n) { | 226 String fourDigits(int n) { |
| 223 int absN = n.abs(); | 227 int absN = n.abs(); |
| 224 String sign = n < 0 ? "-" : ""; | 228 String sign = n < 0 ? "-" : ""; |
| 225 if (absN >= 1000) return "$n"; | 229 if (absN >= 1000) return "$n"; |
| 226 if (absN >= 100) return "${sign}0$absN"; | 230 if (absN >= 100) return "${sign}0$absN"; |
| 227 if (absN >= 10) return "${sign}00$absN"; | 231 if (absN >= 10) return "${sign}00$absN"; |
| 228 if (absN >= 1) return "${sign}000$absN"; | 232 if (absN >= 1) return "${sign}000$absN"; |
| 229 } | 233 } |
| 230 String threeDigits(int n) { | 234 String threeDigits(int n) { |
| 231 if (n >= 100) return "${n}"; | 235 if (n >= 100) return "${n}"; |
| 232 if (n >= 10) return "0${n}"; | 236 if (n >= 10) return "0${n}"; |
| 233 return "00${n}"; | 237 return "00${n}"; |
| 234 } | 238 } |
| 235 String twoDigits(int n) { | 239 String twoDigits(int n) { |
| 236 if (n >= 10) return "${n}"; | 240 if (n >= 10) return "${n}"; |
| 237 return "0${n}"; | 241 return "0${n}"; |
| 238 } | 242 } |
| 239 | 243 |
| 240 String y = fourDigits(year); | 244 String y = fourDigits(year); |
| 241 String m = twoDigits(month); | 245 String m = twoDigits(month); |
| 242 String d = twoDigits(day); | 246 String d = twoDigits(day); |
| 243 String h = twoDigits(hours); | 247 String h = twoDigits(hours); |
| 244 String min = twoDigits(minutes); | 248 String min = twoDigits(minutes); |
| 245 String sec = twoDigits(seconds); | 249 String sec = twoDigits(seconds); |
| 246 String ms = threeDigits(milliseconds); | 250 String ms = threeDigits(milliseconds); |
| 247 if (timeZone.isUtc) { | 251 if (isUtc()) { |
| 248 return "$y-$m-$d $h:$min:$sec.${ms}Z"; | 252 return "$y-$m-$d $h:$min:$sec.${ms}Z"; |
| 249 } else { | 253 } else { |
| 250 return "$y-$m-$d $h:$min:$sec.$ms"; | 254 return "$y-$m-$d $h:$min:$sec.$ms"; |
| 251 } | 255 } |
| 252 } | 256 } |
| 253 | 257 |
| 254 // Adds the [duration] to this Date instance. | 258 // Adds the [duration] to this Date instance. |
| 255 Date add(Duration duration) { | 259 Date add(Duration duration) { |
| 256 return new DateImplementation.fromEpoch(value + duration.inMilliseconds, | 260 return new DateImplementation.fromEpoch(value + duration.inMilliseconds, |
| 257 timeZone); | 261 isUtc()); |
| 258 } | 262 } |
| 259 | 263 |
| 260 // Subtracts the [duration] from this Date instance. | 264 // Subtracts the [duration] from this Date instance. |
| 261 Date subtract(Duration duration) { | 265 Date subtract(Duration duration) { |
| 262 return new DateImplementation.fromEpoch(value - duration.inMilliseconds, | 266 return new DateImplementation.fromEpoch(value - duration.inMilliseconds, |
| 263 timeZone); | 267 isUtc()); |
| 264 } | 268 } |
| 265 | 269 |
| 266 // Returns a [Duration] with the difference of [this] and [other]. | 270 // Returns a [Duration] with the difference of [this] and [other]. |
| 267 Duration difference(Date other) { | 271 Duration difference(Date other) { |
| 268 return new DurationImplementation(milliseconds: value - other.value); | 272 return new DurationImplementation(milliseconds: value - other.value); |
| 269 } | 273 } |
| 270 | 274 |
| 271 final int value; | |
| 272 final TimeZoneImplementation timeZone; | |
| 273 | |
| 274 static final int _SECONDS_YEAR_2035 = 2051222400; | |
| 275 | |
| 276 // Returns the UTC year for the corresponding [secondsSinceEpoch]. | 275 // Returns the UTC year for the corresponding [secondsSinceEpoch]. |
| 277 // It is relatively fast for values in the range 0 to year 2098. | 276 // It is relatively fast for values in the range 0 to year 2098. |
| 278 // Code is adapted from V8. | 277 // Code is adapted from V8. |
| 279 static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) { | 278 static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) { |
| 280 final int DAYS_IN_4_YEARS = 4 * 365 + 1; | 279 final int DAYS_IN_4_YEARS = 4 * 365 + 1; |
| 281 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; | 280 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; |
| 282 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; | 281 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; |
| 283 final int DAYS_1970_TO_2000 = 30 * 365 + 7; | 282 final int DAYS_1970_TO_2000 = 30 * 365 + 7; |
| 284 final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - | 283 final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - |
| 285 DAYS_1970_TO_2000; | 284 DAYS_1970_TO_2000; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 | 431 |
| 433 static int _getHours(int secondsSinceEpoch, bool isUtc) | 432 static int _getHours(int secondsSinceEpoch, bool isUtc) |
| 434 native "DateNatives_getHours"; | 433 native "DateNatives_getHours"; |
| 435 | 434 |
| 436 static int _getMinutes(int secondsSinceEpoch, bool isUtc) | 435 static int _getMinutes(int secondsSinceEpoch, bool isUtc) |
| 437 native "DateNatives_getMinutes"; | 436 native "DateNatives_getMinutes"; |
| 438 | 437 |
| 439 static int _getSeconds(int secondsSinceEpoch, bool isUtc) | 438 static int _getSeconds(int secondsSinceEpoch, bool isUtc) |
| 440 native "DateNatives_getSeconds"; | 439 native "DateNatives_getSeconds"; |
| 441 } | 440 } |
| OLD | NEW |