Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Period type #3818

Merged
merged 29 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e08178e
Add Period type
Akirathan Oct 20, 2022
8d10125
Refactor all days,months,years Integer extension methods to Period.new
Akirathan Oct 20, 2022
539cc7e
Re-enable Period-specific tests
Akirathan Oct 20, 2022
fb90de7
Add "should not mix Duration and Period" test
Akirathan Oct 20, 2022
2c3c955
Implement Date.+.
Akirathan Oct 20, 2022
f398ebe
Refactor Duration.+ and Duration.- to only take Duration as parameter
Akirathan Oct 20, 2022
89a923a
DateTime.+/- supports both Period and Duration
Akirathan Oct 20, 2022
52f2d0d
Add Period_Spec tests
Akirathan Oct 21, 2022
e49915f
Add docs
Akirathan Oct 21, 2022
09077e7
Update CHANGELOG
Akirathan Oct 21, 2022
3865d71
Remove unnecessary call of Date_Time.new
Akirathan Oct 24, 2022
fa2a268
Improve usage of errors
Akirathan Oct 24, 2022
d66c0c1
Fix usage of Duration
Akirathan Oct 25, 2022
18d0a8d
Ignore Period.enso in ParseStdLibTest
Akirathan Oct 25, 2022
5253541
Refactor ensure_period to take action as parameter
Akirathan Oct 26, 2022
b36a46b
Period has another constructor with start_date
Akirathan Oct 26, 2022
d9fac3f
Add tests for Period comparison
Akirathan Oct 26, 2022
f6b3a78
Add Period.days, Period.months, Period.years constructors
Akirathan Oct 26, 2022
30e5796
Fix test with period comparison
Akirathan Oct 26, 2022
7d7d03f
Add shortcut constructors to Duration
Akirathan Oct 26, 2022
151b01a
Fix few tests
Akirathan Oct 26, 2022
2e516da
Add ensure_duration
Akirathan Oct 26, 2022
347605d
Merge branch 'develop' into wip/akirathan/period-183336003
Akirathan Oct 27, 2022
48e8727
Periods are incomparable
Akirathan Oct 28, 2022
05e580b
Split Date.add_work_days in two methods.
Akirathan Oct 28, 2022
679be6c
Duration.== does not throw error
Akirathan Oct 28, 2022
55adca2
Fix typo
Akirathan Oct 28, 2022
a7afda7
Java Duration is an Enso Duration
Akirathan Oct 28, 2022
4904e3a
Time_Of_Day.- checks type of argument
Akirathan Oct 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@
`Table.remove_columns Column_Selector.Blank_Columns` by adding the new column
selector variant.][3812]
- [Implemented `Table.rows` giving access to a vector of rows.][3827]
- [Implemented `Period` type][3818]

[debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
Expand Down Expand Up @@ -356,6 +357,7 @@
[3823]: https://github.com/enso-org/enso/pull/3823
[3827]: https://github.com/enso-org/enso/pull/3827
[3824]: https://github.com/enso-org/enso/pull/3824
[3818]: https://github.com/enso-org/enso/pull/3818

#### Enso Compiler

Expand Down
51 changes: 33 additions & 18 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from Standard.Base import all

import Standard.Base.Data.Time.Duration
import Standard.Base.Data.Time.Period
import Standard.Base.Data.Time.Date_Period

import Standard.Base.Polyglot
Expand All @@ -9,6 +10,8 @@ from Standard.Base.Error.Common import Time_Error_Data, unimplemented
polyglot java import org.enso.base.Time_Utils
polyglot java import java.time.temporal.ChronoField
polyglot java import java.time.temporal.IsoFields
polyglot java import java.time.DateTimeException
polyglot java import java.lang.ArithmeticException

## Obtains the current date from the system clock in the system timezone.

Expand Down Expand Up @@ -139,9 +142,6 @@ parse text pattern=Nothing =

## This type represents a date, often viewed as year-month-day.

Arguments:
- internal_local_date: The internal date representation.

For example, the value "2nd October 2007" can be stored in a `Date`.

This class does not store or represent a time or timezone. Instead, it
Expand Down Expand Up @@ -253,7 +253,7 @@ type Date
end-exclusive manner), by default the end date is not included in the
count. This has the nice property that for example to count the work
days within the next week you can do
`date.work_days_until (date + 7.days)` and it will look at the 7 days
`date.work_days_until (date + (Period.days 7)` and it will look at the 7 days
starting from the current `date` and not 8 days. This also gives us a
property that `date.work_days_until (date.add_work_days N) == N` for
any non-negative N. On the other hand, sometimes we may want the end
Expand All @@ -270,7 +270,7 @@ type Date
example_workdays = Date.new 2020 1 1 . work_days_until (Date.new 2020 1 5)
work_days_until : Date -> Vector Date -> Boolean -> Integer
work_days_until self end holidays=[] include_end_date=False =
if include_end_date then self.work_days_until (end + 1.day) holidays include_end_date=False else
if include_end_date then self.work_days_until (end + (Period.days 1)) holidays include_end_date=False else
weekdays = week_days_between self end
## We count holidays that occurred within the period, but not on the
weekends (as weekend days have already been excluded from the count).
Expand All @@ -293,7 +293,7 @@ type Date

from Standard.Base import Date, Time_Of_Day, Time_Zone

example_to_time = Date.new 2020 2 3 . to_time Time_Of_Day.new Time_Zone.utc
example_to_time = Date.new 2020 2 3 . to_date_time Time_Of_Day.new Time_Zone.utc
to_date_time : Time_Of_Day -> Time_Zone -> Date_Time
to_date_time self (time_of_day=Time_Of_Day.new) (zone=Time_Zone.system) = self.to_time_builtin time_of_day zone

Expand All @@ -307,9 +307,16 @@ type Date

import Standard.Base.Data.Time.Duration

example_add = Date.new 2020 + 6.months
+ : Date_Period -> Date
+ self _ = unimplemented "Date.+"
example_add = Date.new 2020 + (Period.months 6)
+ : Period -> Date ! (Time_Error | Illegal_Argument_Error)
+ self period =
case period of
_ : Period.Period ->
Time_Utils.date_adjust self Time_Utils.AdjustOp.PLUS period.internal_period
_ : Duration.Duration ->
Akirathan marked this conversation as resolved.
Show resolved Hide resolved
Error.throw (Time_Error_Data "Date does not support adding/subtracting Duration. Use Period instead.")
_ ->
Error.throw (Illegal_Argument_Error_Data "Illegal period argument")

## Shift the date by the specified amount of business days.

Expand Down Expand Up @@ -360,7 +367,7 @@ type Date
if ordinal + remaining_days > 5 then 2 else 0

days_to_shift = full_weeks*7 + remaining_days + additional_shift
end = self + days_to_shift.days
end = self + (Period.new days=days_to_shift)

## We have shifted the date so that weekends are taken into account,
but other holidays may have happened during that shift period.
Expand All @@ -378,7 +385,7 @@ type Date
as long as needed to fall on a non-weekend non-holiday
workday.
go end_date =
if holidays.contains end_date || is_weekend end_date then @Tail_Call go (end_date + 1.day) else end_date
if holidays.contains end_date || is_weekend end_date then @Tail_Call go (end_date + (Period.days 1)) else end_date
go end
False ->
## We shift a bit so that if shifting by N full weeks, the 'last'
Expand All @@ -403,7 +410,7 @@ type Date
`days_to_shift` will be negative so `end` will come _before_
`self`.
days_to_shift = full_weeks*7 + remaining_days + additional_shift
end = self + days_to_shift.days
end = self + (Period.new days=days_to_shift)
workdays = end.work_days_until self holidays include_end_date=False

## `days` is negative but `workdays` is positive, `diff` will be
Expand All @@ -416,7 +423,7 @@ type Date
holiday, we need to ensure that we move it - this time
backwards - to the first workday.
go end_date =
if holidays.contains end_date || is_weekend end_date then @Tail_Call go (end_date - 1.day) else end_date
if holidays.contains end_date || is_weekend end_date then @Tail_Call go (end_date - (Period.days 1)) else end_date
go end

## Subtract the specified amount of time from this instant to get another
Expand All @@ -431,9 +438,17 @@ type Date
from Standard.Base import Date
import Standard.Base.Data.Time.Duration

example_subtract = Date.new 2020 - 7.days
- : Date_Period -> Date
- self _ = unimplemented "Date.-"
example_subtract = Date.new 2020 - (Period.days 7)
- : Period -> Date ! (Time_Error | Illegal_Argument_Error)
- self period =
case period of
_ : Period.Period ->
new_java_date = Time_Utils.date_adjust self Time_Utils.AdjustOp.MINUS period.internal_period
new new_java_date.year new_java_date.month new_java_date.day
_ : Duration.Duration ->
Error.throw (Time_Error_Data "Date does not support adding/subtracting Duration. Use Period instead.")
_ ->
Error.throw (Illegal_Argument_Error_Data "Illegal period argument")


## A Date to Json conversion.
Expand Down Expand Up @@ -513,7 +528,7 @@ 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 = (start.start_of Date_Period.Week) + 7.days
start_of_first_full_week = (start.start_of Date_Period.Week) + (Period.days 7)
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
Expand All @@ -529,7 +544,7 @@ week_days_between start end =
_ -> days_between
False ->
# We count the days in the first week up until Friday - the weekend is not counted.
first_week_days = Math.max 0 (Time_Utils.days_between start (start_of_first_full_week - 2.days))
first_week_days = Math.max 0 (Time_Utils.days_between start (start_of_first_full_week - (Period.days 2)))
# We count the days in the last week, not including the weekend.
last_week_days = Math.min (Time_Utils.days_between start_of_last_week end) 5
full_weeks_between * 5 + first_week_days + last_week_days
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from Standard.Base import all

import Standard.Base.Data.Time.Duration
import Standard.Base.Data.Time.Date_Period
import Standard.Base.Data.Time.Time_Period
from Standard.Base.Data.Time import Duration, Period, Date_Period, Time_Period
from Standard.Base.Error.Common import Time_Error

polyglot java import java.time.format.DateTimeFormatter
polyglot java import java.time.temporal.ChronoField
polyglot java import java.time.temporal.IsoFields
polyglot java import java.time.ZonedDateTime
polyglot java import java.lang.ArithmeticException

polyglot java import org.enso.base.Time_Utils
Expand Down Expand Up @@ -380,18 +379,24 @@ type Date_Time
## Add the specified amount of time to this instant to produce a new instant.

Arguments:
- amount: The amount of time to add to this instant.
- amount: The amount of time to add to this instant, either `Duration` for
adding time (hours, minutes, etc.), or `Period` for adding date (days,
months, years).

> Example
Add 15 years and 3 hours to a zoned date time.

from Standard.Base import Date_Time
import Standard.Base.Data.Time.Duration
from Standard.Base.Data.Time import Duration, Period

example_plus = Date_Time.new 2020 + 15.years + (Duration.new hours=3)
+ : Duration -> Date_Time ! Time_Error
example_plus = Date_Time.new 2020 + (Period.years 15) + (Duration.hours 3)
+ : (Duration | Period) -> Date_Time ! Time_Error
+ self amount =
Panic.catch ArithmeticException (self.plus_builtin amount) (err -> Error.throw (Time_Error_Data err.getMessage))
case amount of
duration : Duration.Duration ->
Panic.catch ArithmeticException (self.plus_builtin duration) (err -> Error.throw (Time_Error_Data err.getMessage))
period : Period.Period ->
Akirathan marked this conversation as resolved.
Show resolved Hide resolved
Time_Utils.datetime_adjust self Time_Utils.AdjustOp.PLUS period.internal_period

## Shift the date by the specified amount of business days.

Expand Down Expand Up @@ -434,18 +439,24 @@ type Date_Time
instant.

Arguments:
- amount: The amount of time to subtract from this instant.
- amount: The amount of time to subtract from this instant. Can be either
`Duration` for subtracting time (hours, minutes, etc.), or `Period`
for subtracting days, months and years.

> Example
Subtract 1 year and 9 months from a zoned date time.
Subtract 1 year, 9 months and 12 hours from a zoned date time.

from Standard.Base import Date_Time
import Standard.Base.Data.Time.Duration

example_minus = Date_Time.new 2020 - 1.year - 9.months
- : Duration -> Date_Time ! Time_Error
example_minus = Date_Time.new 2020 - (Period.years 1) - (Period.months 9) - (Duration.hours 5)
- : (Duration | Period) -> Date_Time ! Time_Error
- self amount =
Panic.catch ArithmeticException (self.minus_builtin amount) (err -> Error.throw (Time_Error_Data err.getMessage))
case amount of
duration : Duration.Duration ->
Panic.catch ArithmeticException (self.minus_builtin duration) (err -> Error.throw (Time_Error_Data err.getMessage))
period : Period.Period ->
Time_Utils.datetime_adjust self Time_Utils.AdjustOp.MINUS period.internal_period

## Convert this time to text using the default formatter.

Expand Down
Loading