From cd10b5d34d7b2d393b7e1af865dc63a4fc00bab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Wa=C5=9Bko?= Date: Sat, 24 Sep 2022 00:14:35 +0200 Subject: [PATCH] Add `Date_Period.Week` to `start_of` and `end_of` methods (#3733) Implements https://www.pivotaltracker.com/story/show/183349732 --- CHANGELOG.md | 2 ++ .../Base/0.0.0-dev/src/Data/Time/Date.enso | 4 ++-- .../0.0.0-dev/src/Data/Time/Date_Period.enso | 8 ++++++++ .../0.0.0-dev/src/Data/Time/Day_Of_Week.enso | 13 ++++++++++++ .../main/java/org/enso/base/Time_Utils.java | 8 -------- .../org/enso/base/time/Date_Period_Utils.java | 6 ++++++ test/Tests/src/Data/Time/Date_Spec.enso | 12 ++++++++++- test/Tests/src/Data/Time/Date_Time_Spec.enso | 20 ++++++++++++++++--- 8 files changed, 59 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19cf4403eb1b..0580ebe59fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -201,6 +201,7 @@ - [Implemented `work_days_until` for counting work dys between dates and `add_work_days` which allows to shift a date by a number of work days.][3726] - [Added `query` and `read` functions to Database connections.][3727] +- [Added `Date_Period.Week` to `start_of` and `end_of` methods.][3733] [debug-shortcuts]: https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug @@ -321,6 +322,7 @@ [3695]: https://github.com/enso-org/enso/pull/3695 [3726]: https://github.com/enso-org/enso/pull/3726 [3727]: https://github.com/enso-org/enso/pull/3727 +[3733]: https://github.com/enso-org/enso/pull/3733 #### Enso Compiler diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso index 0277cb284768..c08c7b3cde48 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso @@ -511,8 +511,8 @@ week_days_between start end = starting point), the last week (containing the end point), and the full weeks in between those. In some cases there may be no weeks in-between and the first and last week can be the same week. - start_of_first_full_week = Time_Utils.start_of_next_week start - start_of_last_week = Time_Utils.start_of_week end + start_of_first_full_week = (start.start_of Date_Period.Week) + 7.days + start_of_last_week = end.start_of Date_Period.Week full_weeks_between = (Time_Utils.days_between start_of_first_full_week start_of_last_week).div 7 case full_weeks_between < 0 of # Either start is before end or they both lie within the same week. diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso index a4aeaabc0265..83b858de9419 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Period.enso @@ -11,6 +11,12 @@ type Date_Period Quarter Month + ## Represents a 7-day week starting at a given day. + + By default, the first day of the week is Monday, but this can be adjusted + to any other day. + Week (first_day:Day_Of_Week = Day_Of_Week.Monday) + ## PRIVATE This method could be replaced with matching on `Date_Period` supertype if/when that is supported. @@ -24,6 +30,7 @@ type Date_Period Year -> TemporalAdjusters.firstDayOfYear Quarter -> Date_Period_Utils.quarter_start Month -> TemporalAdjusters.firstDayOfMonth + Week first_day -> TemporalAdjusters.previousOrSame first_day.to_java (Time_Utils.utils_for date).apply_adjuster date adjuster ## PRIVATE @@ -33,4 +40,5 @@ type Date_Period Year -> TemporalAdjusters.lastDayOfYear Quarter -> Date_Period_Utils.quarter_end Month -> TemporalAdjusters.lastDayOfMonth + Week first_day -> Date_Period_Utils.end_of_week first_day.to_java (Time_Utils.utils_for date).apply_adjuster date adjuster diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Day_Of_Week.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Day_Of_Week.enso index 7c9fea48ffa0..dafac8ff28cc 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Day_Of_Week.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Day_Of_Week.enso @@ -1,5 +1,7 @@ from Standard.Base import all +polyglot java import java.time.DayOfWeek + type Day_Of_Week Sunday @@ -36,6 +38,17 @@ type Day_Of_Week shifted + if start_at_zero then 0 else 1 + ## PRIVATE + to_java : DayOfWeek + to_java self = case self of + Sunday -> DayOfWeek.SUNDAY + Monday -> DayOfWeek.MONDAY + Tuesday -> DayOfWeek.TUESDAY + Wednesday -> DayOfWeek.WEDNESDAY + Thursday -> DayOfWeek.THURSDAY + Friday -> DayOfWeek.FRIDAY + Saturday -> DayOfWeek.SATURDAY + ## Convert from an integer to a Day_Of_Week Arguments: diff --git a/std-bits/base/src/main/java/org/enso/base/Time_Utils.java b/std-bits/base/src/main/java/org/enso/base/Time_Utils.java index 01276afb214a..1adb018b7873 100644 --- a/std-bits/base/src/main/java/org/enso/base/Time_Utils.java +++ b/std-bits/base/src/main/java/org/enso/base/Time_Utils.java @@ -239,12 +239,4 @@ public static ZoneOffset get_datetime_offset(ZonedDateTime datetime) { public static long days_between(LocalDate start, LocalDate end) { return ChronoUnit.DAYS.between(start, end); } - - public static LocalDate start_of_week(LocalDate date) { - return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); - } - - public static LocalDate start_of_next_week(LocalDate date) { - return date.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); - } } diff --git a/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java b/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java index 6972c4a6f47a..bf4b5f882638 100644 --- a/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java +++ b/std-bits/base/src/main/java/org/enso/base/time/Date_Period_Utils.java @@ -1,5 +1,6 @@ package org.enso.base.time; +import java.time.DayOfWeek; import java.time.YearMonth; import java.time.temporal.*; @@ -22,4 +23,9 @@ public class Date_Period_Utils implements TimeUtilsBase { .with(ChronoField.MONTH_OF_YEAR, month) .with(TemporalAdjusters.lastDayOfMonth()); }; + + public static TemporalAdjuster end_of_week(DayOfWeek first_day) { + DayOfWeek last_day = first_day.minus(1); + return (Temporal temporal) -> temporal.with(TemporalAdjusters.nextOrSame(last_day)); + } } diff --git a/test/Tests/src/Data/Time/Date_Spec.enso b/test/Tests/src/Data/Time/Date_Spec.enso index b35d8b9271bd..54e16493ffc8 100644 --- a/test/Tests/src/Data/Time/Date_Spec.enso +++ b/test/Tests/src/Data/Time/Date_Spec.enso @@ -141,6 +141,12 @@ spec_with name create_new_date parse_date = d1.end_of Date_Period.Quarter . should_equal (Date.new 2022 9 30) d1.start_of Date_Period.Month . should_equal (Date.new 2022 9 1) d1.end_of Date_Period.Month . should_equal (Date.new 2022 9 30) + d1.start_of (Date_Period.Week) . should_equal (Date.new 2022 9 12) + d1.end_of (Date_Period.Week) . should_equal (Date.new 2022 9 18) + d1.start_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date.new 2022 9 11) + d1.end_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date.new 2022 9 17) + d1.start_of (Date_Period.Week first_day=Day_Of_Week.Saturday) . should_equal (Date.new 2022 9 10) + d1.end_of (Date_Period.Week first_day=Day_Of_Week.Saturday) . should_equal (Date.new 2022 9 16) d2 = create_new_date 2022 2 7 d2.start_of Date_Period.Quarter . should_equal (Date.new 2022 1 1) @@ -148,11 +154,15 @@ spec_with name create_new_date parse_date = d2.start_of Date_Period.Month . should_equal (Date.new 2022 2 1) d2.end_of Date_Period.Month . should_equal (Date.new 2022 2 28) - d3 = create_new_date 2020 2 17 + d3 = create_new_date 2020 2 19 d3.start_of Date_Period.Year . should_equal (Date.new 2020 1 1) d3.end_of Date_Period.Year . should_equal (Date.new 2020 12 31) d3.start_of Date_Period.Month . should_equal (Date.new 2020 2 1) d3.end_of Date_Period.Month . should_equal (Date.new 2020 2 29) + d3.start_of (Date_Period.Week) . should_equal (Date.new 2020 2 17) + d3.end_of (Date_Period.Week) . should_equal (Date.new 2020 2 23) + d3.start_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date.new 2020 2 16) + d3.end_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date.new 2020 2 22) d4 = create_new_date 1970 12 31 d4.start_of Date_Period.Year . should_equal (Date.new 1970 1 1) diff --git a/test/Tests/src/Data/Time/Date_Time_Spec.enso b/test/Tests/src/Data/Time/Date_Time_Spec.enso index b8163a15e3ef..65410aabe654 100644 --- a/test/Tests/src/Data/Time/Date_Time_Spec.enso +++ b/test/Tests/src/Data/Time/Date_Time_Spec.enso @@ -324,18 +324,32 @@ spec_with name create_new_datetime parse_datetime nanoseconds_loss_in_precision= d1.end_of Date_Period.Quarter . should_equal (Date_Time.new 2022 9 30 23 59 59 max_nanos) d1.start_of Date_Period.Month . should_equal (Date_Time.new 2022 9 1) d1.end_of Date_Period.Month . should_equal (Date_Time.new 2022 9 30 23 59 59 max_nanos) - - d2 = create_new_datetime 2022 2 7 12 34 56 123456789 + d1.start_of (Date_Period.Week) . should_equal (Date_Time.new 2022 9 12) + d1.end_of (Date_Period.Week) . should_equal (Date_Time.new 2022 9 18 23 59 59 max_nanos) + d1.start_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2022 9 11) + d1.end_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2022 9 17 23 59 59 max_nanos) + d1.start_of (Date_Period.Week first_day=Day_Of_Week.Saturday) . should_equal (Date_Time.new 2022 9 10) + d1.end_of (Date_Period.Week first_day=Day_Of_Week.Saturday) . should_equal (Date_Time.new 2022 9 16 23 59 59 max_nanos) + + d2 = create_new_datetime 2022 2 6 12 34 56 123456789 d2.start_of Date_Period.Quarter . should_equal (Date_Time.new 2022 1 1) d2.end_of Date_Period.Quarter . should_equal (Date_Time.new 2022 3 31 23 59 59 max_nanos) d2.start_of Date_Period.Month . should_equal (Date_Time.new 2022 2 1) d2.end_of Date_Period.Month . should_equal (Date_Time.new 2022 2 28 23 59 59 max_nanos) + d2.start_of (Date_Period.Week) . should_equal (Date_Time.new 2022 1 31) + d2.end_of (Date_Period.Week) . should_equal (Date_Time.new 2022 2 6 23 59 59 max_nanos) + d2.start_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2022 2 6) + d2.end_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2022 2 12 23 59 59 max_nanos) - d3 = create_new_datetime 2020 2 17 + d3 = create_new_datetime 2020 2 19 d3.start_of Date_Period.Year . should_equal (Date_Time.new 2020 1 1) d3.end_of Date_Period.Year . should_equal (Date_Time.new 2020 12 31 23 59 59 max_nanos) d3.start_of Date_Period.Month . should_equal (Date_Time.new 2020 2 1) d3.end_of Date_Period.Month . should_equal (Date_Time.new 2020 2 29 23 59 59 max_nanos) + d3.start_of (Date_Period.Week) . should_equal (Date_Time.new 2020 2 17) + d3.end_of (Date_Period.Week) . should_equal (Date_Time.new 2020 2 23 23 59 59 max_nanos) + d3.start_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2020 2 16) + d3.end_of (Date_Period.Week first_day=Day_Of_Week.Sunday) . should_equal (Date_Time.new 2020 2 22 23 59 59 max_nanos) d4 = create_new_datetime 1970 12 31 23 59 59 max_nanos d4.start_of Date_Period.Year . should_equal (Date_Time.new 1970 1 1)