| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 Google Inc. All Rights Reserved. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 | |
| 15 part of quiver.time; | |
| 16 | |
| 17 /// Returns current time. | |
| 18 typedef DateTime TimeFunction(); | |
| 19 | |
| 20 /// Return current system time. | |
| 21 DateTime systemTime() => new DateTime.now(); | |
| 22 | |
| 23 /// Days in a month. This array uses 1-based month numbers, i.e. January is | |
| 24 /// the 1-st element in the array, not the 0-th. | |
| 25 const _DAYS_IN_MONTH = | |
| 26 const [ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; | |
| 27 | |
| 28 int _daysInMonth(int year, int month) => (month == DateTime.FEBRUARY && | |
| 29 _isLeapYear(year)) ? 29 : _DAYS_IN_MONTH[month]; | |
| 30 | |
| 31 bool _isLeapYear(int year) => | |
| 32 (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); | |
| 33 | |
| 34 /// Takes a [date] that may be outside the allowed range of dates for a given | |
| 35 /// [month] in a given [year] and returns the closest date that is within the | |
| 36 /// allowed range. | |
| 37 /// | |
| 38 /// For example: | |
| 39 /// | |
| 40 /// February 31, 2013 => February 28, 2013 | |
| 41 /// | |
| 42 /// When jumping from month to month or from leap year to common year we may | |
| 43 /// end up in a month that has fewer days than the month we are jumping from. | |
| 44 /// In that case it is impossible to preserve the exact date. So we "clamp" the | |
| 45 /// date value to fit within the month. For example, jumping from March 31 one | |
| 46 /// month back takes us to February 28 (or 29 during a leap year), as February | |
| 47 /// doesn't have 31-st date. | |
| 48 int _clampDate(int date, int year, int month) => | |
| 49 date.clamp(1, _daysInMonth(year, month)); | |
| 50 | |
| 51 /// Provides points in time relative to the current point in time, for example: | |
| 52 /// now, 2 days ago, 4 weeks from now, etc. | |
| 53 /// | |
| 54 /// This class is designed with testability in mind. The current point in time | |
| 55 /// (or [now()]) is defined by a [TimeFunction]. By supplying your own time | |
| 56 /// function or by using fixed clock (see constructors), you can control | |
| 57 /// exactly what time a [Clock] returns and base your test expectations on | |
| 58 /// that. See specific constructors for how to supply time functions. | |
| 59 class Clock { | |
| 60 final TimeFunction _time; | |
| 61 | |
| 62 /// Creates a clock based on the given [timeFunc]. | |
| 63 /// | |
| 64 /// If [timeFunc] is not provided, creates [Clock] based on system clock. | |
| 65 /// | |
| 66 /// Custom [timeFunc] can be useful in unit-tests. For example, you might | |
| 67 /// want to control what time it is now and set date and time expectations in | |
| 68 /// your test cases. | |
| 69 const Clock([TimeFunction timeFunc = systemTime]) : _time = timeFunc; | |
| 70 | |
| 71 /// Creates [Clock] that returns fixed [time] value. Useful in unit-tests. | |
| 72 Clock.fixed(DateTime time) : _time = (() => time); | |
| 73 | |
| 74 /// Returns current time. | |
| 75 DateTime now() => _time(); | |
| 76 | |
| 77 /// Returns the point in time [Duration] amount of time ago. | |
| 78 DateTime agoBy(Duration duration) => now().subtract(duration); | |
| 79 | |
| 80 /// Returns the point in time [Duration] amount of time from now. | |
| 81 DateTime fromNowBy(Duration duration) => now().add(duration); | |
| 82 | |
| 83 /// Returns the point in time that's given amount of time ago. The | |
| 84 /// amount of time is the sum of individual parts. Parts are compatible with | |
| 85 /// ones defined in [Duration]. | |
| 86 DateTime ago({int days: 0, int hours: 0, int minutes: 0, int seconds: 0, | |
| 87 int milliseconds: 0, int microseconds: 0}) => agoBy(new Duration( | |
| 88 days: days, | |
| 89 hours: hours, | |
| 90 minutes: minutes, | |
| 91 seconds: seconds, | |
| 92 milliseconds: milliseconds, | |
| 93 microseconds: microseconds)); | |
| 94 | |
| 95 /// Returns the point in time that's given amount of time from now. The | |
| 96 /// amount of time is the sum of individual parts. Parts are compatible with | |
| 97 /// ones defined in [Duration]. | |
| 98 DateTime fromNow({int days: 0, int hours: 0, int minutes: 0, int seconds: 0, | |
| 99 int milliseconds: 0, int microseconds: 0}) => fromNowBy(new Duration( | |
| 100 days: days, | |
| 101 hours: hours, | |
| 102 minutes: minutes, | |
| 103 seconds: seconds, | |
| 104 milliseconds: milliseconds, | |
| 105 microseconds: microseconds)); | |
| 106 | |
| 107 /// Return the point in time [micros] microseconds ago. | |
| 108 DateTime microsAgo(int micros) => ago(microseconds: micros); | |
| 109 | |
| 110 /// Return the point in time [micros] microseconds from now. | |
| 111 DateTime microsFromNow(int micros) => fromNow(microseconds: micros); | |
| 112 | |
| 113 /// Return the point in time [millis] milliseconds ago. | |
| 114 DateTime millisAgo(int millis) => ago(milliseconds: millis); | |
| 115 | |
| 116 /// Return the point in time [millis] milliseconds from now. | |
| 117 DateTime millisFromNow(int millis) => fromNow(milliseconds: millis); | |
| 118 | |
| 119 /// Return the point in time [seconds] ago. | |
| 120 DateTime secondsAgo(int seconds) => ago(seconds: seconds); | |
| 121 | |
| 122 /// Return the point in time [seconds] from now. | |
| 123 DateTime secondsFromNow(int seconds) => fromNow(seconds: seconds); | |
| 124 | |
| 125 /// Return the point in time [minutes] ago. | |
| 126 DateTime minutesAgo(int minutes) => ago(minutes: minutes); | |
| 127 | |
| 128 /// Return the point in time [minutes] from now. | |
| 129 DateTime minutesFromNow(int minutes) => fromNow(minutes: minutes); | |
| 130 | |
| 131 /// Return the point in time [hours] ago. | |
| 132 DateTime hoursAgo(int hours) => ago(hours: hours); | |
| 133 | |
| 134 /// Return the point in time [hours] from now. | |
| 135 DateTime hoursFromNow(int hours) => fromNow(hours: hours); | |
| 136 | |
| 137 /// Return the point in time [days] ago. | |
| 138 DateTime daysAgo(int days) => ago(days: days); | |
| 139 | |
| 140 /// Return the point in time [days] from now. | |
| 141 DateTime daysFromNow(int days) => fromNow(days: days); | |
| 142 | |
| 143 /// Return the point in time [weeks] ago. | |
| 144 DateTime weeksAgo(int weeks) => ago(days: 7 * weeks); | |
| 145 | |
| 146 /// Return the point in time [weeks] from now. | |
| 147 DateTime weeksFromNow(int weeks) => fromNow(days: 7 * weeks); | |
| 148 | |
| 149 /// Return the point in time [months] ago on the same date. | |
| 150 DateTime monthsAgo(int months) { | |
| 151 var time = now(); | |
| 152 var m = (time.month - months - 1) % 12 + 1; | |
| 153 var y = time.year - (months + 12 - time.month) ~/ 12; | |
| 154 var d = _clampDate(time.day, y, m); | |
| 155 return new DateTime( | |
| 156 y, m, d, time.hour, time.minute, time.second, time.millisecond); | |
| 157 } | |
| 158 | |
| 159 /// Return the point in time [months] from now on the same date. | |
| 160 DateTime monthsFromNow(int months) { | |
| 161 var time = now(); | |
| 162 var m = (time.month + months - 1) % 12 + 1; | |
| 163 var y = time.year + (months + time.month - 1) ~/ 12; | |
| 164 var d = _clampDate(time.day, y, m); | |
| 165 return new DateTime( | |
| 166 y, m, d, time.hour, time.minute, time.second, time.millisecond); | |
| 167 } | |
| 168 | |
| 169 /// Return the point in time [years] ago on the same date. | |
| 170 DateTime yearsAgo(int years) { | |
| 171 var time = now(); | |
| 172 var y = time.year - years; | |
| 173 var d = _clampDate(time.day, y, time.month); | |
| 174 return new DateTime(y, time.month, d, time.hour, time.minute, time.second, | |
| 175 time.millisecond); | |
| 176 } | |
| 177 | |
| 178 /// Return the point in time [years] from now on the same date. | |
| 179 DateTime yearsFromNow(int years) => yearsAgo(-years); | |
| 180 } | |
| OLD | NEW |