| # Dart Language and Library Newsletter |
| 2017-10-20 |
| @floitschG |
| |
| Welcome to the Dart Language and Library Newsletter. |
| |
| ## DateTime |
| This week's newsletter is all about `DateTime`. It is shorter than usual, but that's because there is an accompanying blog post, which contains lots of additional related information: https://medium.com/@florian_32814/date-time-526a4f86badb |
| |
| As mentioned in the post, we are in the process of refactoring the `DateTime` class in Dart. We want to make it less error-prone for our developers to use it for calendar-dates. Concretely, we will provide date-specific constructors and methods: |
| ``` dart |
| /** |
| * Constructs a [DateTime] instance with the current date. |
| * |
| * The resulting [DateTime] is in the UTC timezone and has the time set to 00:00. |
| */ |
| factory DateTime.today(); |
| |
| /** |
| * Constructs a [DateTime] for the given date. |
| * |
| * The resulting [DateTime] is in the UTC timezone and has the time set to 00:00. |
| */ |
| DateTime.date(int year, int month, int day); |
| |
| /** |
| * Returns this instance suitable for date computations. |
| * |
| * The resulting DateTime is in the UTC timezone and has the time set to 00:00. |
| */ |
| DateTime toDate() => new DateTime.date(year, month, day); |
| |
| /** |
| * Returns which day of the year this DateTime represents. |
| * |
| * The 1st of January returns 1. |
| */ |
| int get dayInYear; |
| } |
| ``` |
| As can be seen, these constructors and members encourage the use of `DateTime` for calendar-dates in a safe way. They all default to UTC, where daylight saving is not an issue. |
| |
| We furthermore want to make it easier to adjust a given `DateTime` instance. One common operation is to add a full month or day to a given date-time and to expect that the clock time stays unchanged. Because of daylight saving this is too cumbersome with the current `DateTime` API. In Dart 2.0 we plan to refactor the existing `add` method (in a breaking way) to support such operations: |
| ``` dart |
| /** |
| * Returns a new [DateTime] instance with the provided arguments added to |
| * to [this]. |
| * |
| * Adding a specific number of months will clamp the day, if the resulting |
| * day would not be in the same month anymore: |
| * |
| * ``` |
| * new DateTime(2017, 03, 31).add(months: 1); // => 2017-04-30. |
| * ``` |
| * |
| * Days are added in such a way that the resulting time is the same (if that's |
| * possible). When daylight saving changes occur, adding a single [day] might |
| * add as little as 23, and as much as 25 hours. |
| * |
| * The arguments are added in the following way: |
| * * Compute a new clock-time using [microseconds], [milliseconds], [seconds], |
| * [minutes], [hours]. At this time, days are assumed to be 24 hours long |
| * (without any daylight saving changes). If any unit overflows or |
| * underflows, the next higher unit is updated correspondingly. |
| * * Any over- or underflow days are added to the [days] value. |
| * * A new calendar date is computed by adding 12 * [years] + [months] months |
| * to the current calendar date. If necessary, the date is then clamped. |
| * * Once the date is valid, the updated [days] value is added to the |
| * calendar date. |
| * * The new date and time values are used to compute a new [DateTime] as if |
| * the [DateTime] constructor was called. Non-existing or ambiguous times |
| * (because of daylight saving changes) are resolved at this point. |
| * * Finally, the [duration] is added to the result of this computation. |
| * |
| * All arguments may be negative. |
| * ``` |
| * var tomorrowTwoHoursEarlier = date.add(days: 1, hours: -2); |
| * var lastDayOfMonth = date.with(day: 1).add(month: 1, days: -1); |
| * ``` |
| */ |
| // All values default to 0 (or a duration of 0). |
| DateTime add({int years, int months, int days, int hours, |
| int minutes, int seconds, int milliseconds, int microseconds, |
| Duration duration}); |
| ``` |
| As can be seen by the documentation, the operation is not trivial anymore. This is a good thing: otherwise our users would need to think about this themselves. |
| |
| While the change to `DateTime.add` is breaking, the work-around is simple: `dt.add(someDuration)` becomes simply `dt.add(duration: someDuration)`. |
| |
| The second common operation is to replace just one property of the instance. We will provide the `with` method for this purpose: |
| ``` dart |
| /** |
| * Returns a [DateTime] instance with the provided arguments replaced by the |
| * new values. |
| * |
| * The returned DateTime is constructed as if the [DateTime] constructor was |
| * called. This means that over and underflows are allowed. |
| */ |
| DateTime with({int year, int month, int day, int hour, int minute, int second, |
| int millisecond, int microsecond, bool isUtc}); |
| ``` |
| This change requires a small modification to the Dart language, because `with` is currently a keyword. It is, however, only used for mixin applications, which means that we can make `with` a built-in identifier (which is allowed to be a method-name) without complicating Dart's parser. |
| |
| Finally, we will improve the `DateTime.parse` method to support more formats (in particular RFC1123), and add a method to print the given date-time as RFC1123 (the format used for cookies). |
| |
| Altogether, we hope that these changes will make Dart's `DateTime` class less error-prone, more convenient, and more versatile. |