/*----------------------------------------------------------------------------
   Copyright 2012-2021, Microsoft Research, Daan Leijen

   Licensed under the Apache License, Version 2.0 ("The Licence"). You may not
   use this file except in compliance with the License. A copy of the License
   can be found in the LICENSE file at the root of this distribution.
----------------------------------------------------------------------------*/

/* Calendars.

  A Calendar determines how a `:date` and `:clock` relates to an `:instant` in time
  with respect to a `:timezone`. These functions turn `:instant`'s into "human" dates.
  Months, days etc. are always 1-based.
*/
module std/time/calendarstd/time/calendar

import std/num/ddoublestd/num/ddouble
import std/time/timestampstd/time/timestamp
import std/time/durationstd/time/duration
import std/time/instantstd/time/instant
import std/time/utcstd/time/utc
import std/time/datestd/time/date

extern import
  c  file "calendar-inline.c"
  cs file "calendar-inline.cs"
  js file "calendar-inline.js"

// A Calendar determines how a `:date` and `:clock` relates to an `:instant` in time.
abstract struct calendarstd/time/calendar/calendar: V
  pub namestd/time/calendar/calendar/name: (calendar : calendar) -> string        : stringstd/core/types/string: V
  pub long-namestd/time/calendar/calendar/long-name: (calendar : calendar) -> string   : stringstd/core/types/string: V
  //timescale   : timescale
  pub month-prefixstd/time/calendar/calendar/month-prefix: (calendar : calendar) -> string: stringstd/core/types/string: V
  pub show-erastd/time/calendar/calendar/show-era: (calendar : calendar) -> ((date) -> string)    : (datestd/time/date/date: V) -> stringstd/core/types/string: V
  instant-to-dcstd/time/calendar/calendar/instant-to-dc: (calendar : calendar) -> ((i : instant, tzdelta : duration) -> (date, clock)) : (i:instantstd/time/instant/instant: V,tzdelta:durationstd/time/duration/duration: V) -> (std/core/types/tuple2: (V, V) -> Vdatestd/time/date/date: V,clockstd/time/date/clock: V)
  dc-to-instantstd/time/calendar/calendar/dc-to-instant: (calendar : calendar) -> ((date, clock, timezone, timescale) -> instant) : (datestd/time/date/date: V,clockstd/time/date/clock: V,timezonestd/time/calendar/timezone: V,timescalestd/time/instant/timescale: V) -> instantstd/time/instant/instant: V
  days-to-datestd/time/calendar/calendar/days-to-date: (calendar : calendar) -> ((days : int) -> date)  : (days:intstd/core/types/int: V) -> datestd/time/date/date: V
  date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int)  : (date:datestd/time/date/date: V) -> intstd/core/types/int: V


// Check if two calendars use the same date calculations. (Display of era names etc. may differ)
pub fun (==)std/time/calendar/(==): (c1 : calendar, c2 : calendar) -> bool( c1c1: calendar : calendarstd/time/calendar/calendar: V, c2c2: calendar : calendarstd/time/calendar/calendar: V )result: -> total bool : boolstd/core/types/bool: V
  (c1c1: calendar.long-namestd/time/calendar/calendar/long-name: (calendar : calendar) -> string ==std/core/string/(==): (string, string) -> bool c2c2: calendar.long-namestd/time/calendar/calendar/long-name: (calendar : calendar) -> string)

/*----------------------------------------------------------------------------
  Time zone
----------------------------------------------------------------------------*/

// A `:timezone` determines a time offset with respect to the UTC / GMT timezone. For
// using general time zones, see the [`std/time/timezone`](std_time_timezone.html) module.\
// The `tz-utc` and `tz-local` time zones are used for UTC/GMT time and the local system time.\
// The `name` field contains the time zone name as IANA timezone identifier.
// The `utc-delta` field returns the time zone offset
// relative to UTC (for GMT-08:00 it returns a duration of `-8*3600` seconds) and the abbreviated
// time zone name (``PDT`` for example).\
// The optional `utc-inverse` field returns for an instant in the time zone, the associated UTC time.
// By default it returns `Nothing` in which case a generic algorithm is used to determine the
// inverse.
abstract struct timezonestd/time/calendar/timezone: V
  pub namename: string    : stringstd/core/types/string: V
  utc-deltautc-delta: (instant) -> (duration, string)   : (instantstd/time/instant/instant: V) -> (std/core/types/tuple2: (V, V) -> Vdurationstd/time/duration/duration: V,stringstd/core/types/string: V)
  utc-inverseutc-inverse: (instant) -> maybe<instant> : (instantstd/time/instant/instant: V) -> maybestd/core/types/maybe: V -> V<instantstd/time/instant/instant: V> = fnfn: (i : instant) -> maybe<instant>(ii: instant) { Nothingstd/core/types/Nothing: forall<a> maybe<a> }


// Same timezone?
pub fun timezone/(==)std/time/calendar/timezone/(==): (tz1 : timezone, tz2 : timezone) -> bool( tz1tz1: timezone : timezonestd/time/calendar/timezone: V, tz2tz2: timezone : timezonestd/time/calendar/timezone: V )result: -> total bool : boolstd/core/types/bool: V
  (tz1tz1: timezone.namestd/time/calendar/timezone/name: (timezone : timezone) -> string ==std/core/string/(==): (string, string) -> bool tz2tz2: timezone.namestd/time/calendar/timezone/name: (timezone : timezone) -> string)

// Is this the UTC timezone?
pub fun is-tz-utcstd/time/calendar/is-tz-utc: (tz : timezone) -> bool( tztz: timezone : timezonestd/time/calendar/timezone: V )result: -> total bool : boolstd/core/types/bool: V
  tztz: timezone ==std/time/calendar/timezone/(==): (tz1 : timezone, tz2 : timezone) -> bool tz-utcstd/time/calendar/tz-utc: timezone

// Create a time zone with a fixed number of hours and optional minutes (=`0`) difference from UTC/GMT.
// The time zone name and abbreviation is optional, and the default name
// will reflect the offset from UTC, for example `"UTC+1:20"`, or `"UTC-8"`.
// The default abbreviation is the empty string.
// The sign of the minutes will be matched to the hours (unless `hours` is `0`).
// For example, `tz-fixed(-1,30)` gives a time zone offset of -90 minutes, "UTC-1:30".
// Returns `tz-utc` if both `hours` and `mins` are zero.
pub fun tz-fixedstd/time/calendar/tz-fixed: (hours : int, mins : ? int, name : ? string, abbrv : ? string, hourwidth : ? int) -> timezone( hourshours: int: intstd/core/types/int: V, minsmins: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, namename: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, abbrvabbrv: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, hourwidthhourwidth: ? int : intstd/core/types/int: V = 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
)result: -> total timezone : timezonestd/time/calendar/timezone: V if hourshours: int.is-zerostd/core/int/is-zero: (x : int) -> bool &&std/core/types/(&&): (x : bool, y : bool) -> bool minsmins: int.is-zerostd/core/int/is-zero: (x : int) -> bool then returnreturn: timezone tz-utcstd/time/calendar/tz-utc: timezone val xminsxmins: int = if hourshours: int.is-posstd/core/int/is-pos: (i : int) -> bool then minsmins: int.absstd/core/int/abs: (i : int) -> int elif hourshours: int.is-negstd/core/int/is-neg: (i : int) -> bool then (minsmins: int.absstd/core/int/abs: (i : int) -> int).negatestd/core/int/negate: (i : int) -> int else minsmins: int val secssecs: int = hourshours: int*std/core/int/(*): (int, int) -> int3600literal: int
dec = 3600
hex16= 0x0E10
bit16= 0b0000111000010000
+std/core/int/(+): (x : int, y : int) -> int xminsxmins: int*std/core/int/(*): (int, int) -> int60literal: int
dec = 60
hex8 = 0x3C
bit8 = 0b00111100
val tzonenametzonename: string = namename: string ||std/core/string/(||): (x : string, y : string) -> string ("UTC"literal: string
count= 3
++std/core/types/(++): (x : string, y : string) -> string (if secssecs: int.is-negstd/core/int/is-neg: (i : int) -> bool then "-"literal: string
count= 1
else "+"literal: string
count= 1
) ++std/core/types/(++): (x : string, y : string) -> string hourshours: int.absstd/core/int/abs: (i : int) -> int.showstd/core/int/show: (i : int) -> string.pad-leftstd/core/string/pad-left: (s : string, width : int, fill : ? char) -> string(hourwidthhourwidth: int,'0'literal: char
unicode= u0030
) ++std/core/types/(++): (x : string, y : string) -> string (if minsmins: int.is-zerostd/core/int/is-zero: (x : int) -> bool then ""literal: string
count= 0
else ":"literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string minsmins: int.absstd/core/int/abs: (i : int) -> int.showstd/core/int/show: (i : int) -> string.pad-leftstd/core/string/pad-left: (s : string, width : int, fill : ? char) -> string(2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
,'0'literal: char
unicode= u0030
))) val deltadelta: duration = durationstd/time/duration/int/duration: (secs : int, frac : ? float64) -> duration(secssecs: int) tz-fixedstd/time/calendar/string/tz-fixed: (name : string, delta : duration, abbrv : ? string) -> timezone(tzonenametzonename: string,deltadelta: duration,abbrvabbrv: string
) fun string/tz-fixedstd/time/calendar/string/tz-fixed: (name : string, delta : duration, abbrv : ? string) -> timezone( namename: string : stringstd/core/types/string: V, deltadelta: duration : durationstd/time/duration/duration: V, abbrvabbrv: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
)result: -> total timezone : timezonestd/time/calendar/timezone: V Timezone( namename: string, fnfn: (i : instant) -> (duration, string)(ii: instant) { (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)deltadelta: duration,abbrvabbrv: string)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) }, fnfn: (i : instant) -> maybe<instant>(ii: instant) { if deltadelta: duration.is-zerostd/time/duration/is-zero: (d : duration) -> bool then Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(ii: instant) else Nothingstd/core/types/Nothing: forall<a> maybe<a> }
) // The standard UTC time zone with a 0 delta. pub val tz-utcstd/time/calendar/tz-utc: timezone : timezonestd/time/calendar/timezone: V = tz-fixedstd/time/calendar/string/tz-fixed: (name : string, delta : duration, abbrv : ? string) -> timezone("UTC"literal: string
count= 3
,zerostd/time/duration/zero: duration
) // Return the local timezone on the current system. pub fun tz-localstd/time/calendar/tz-local: () -> ndet timezone()result: -> ndet timezone : ndetstd/core/types/ndet: X timezonestd/time/calendar/timezone: V val tztz: local-timezone = local-get-timezonestd/time/calendar/local-get-timezone: () -> ndet local-timezone() // get it once so the `Timezone` itself is immutable! Timezone( ""literal: string
count= 0
, fnfn: (i : instant) -> (duration, string)(ii: instant) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ofsofs: float64,abbrvabbrv: string)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = local-utc-deltastd/time/calendar/local-utc-delta: (tz : local-timezone, i : float64) -> (float64, string)(tztz: local-timezone, ii: instant.unix-timestampstd/time/utc/unix-timestamp: (i : instant) -> ddouble.float64std/num/ddouble/float64: (x : ddouble) -> float64) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)durationstd/time/duration/float64/duration: (secs : float64) -> duration(ofsofs: float64),abbrvabbrv: string)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)
) // A local timezone structure provided by the host system type local-timezonestd/time/calendar/local-timezone: V // Get the current local timezone structure. // The timezone name is allowed to be the empty string. extern local-get-timezonestd/time/calendar/local-get-timezone: () -> ndet local-timezone() : ndetstd/core/types/ndet: X local-timezonestd/time/calendar/local-timezone: V c "kk_local_get_timezone" cs "_Calendar.LocalTimeZone" js "_local_get_timezone" // Return the utc delta in fractional seconds given a local timezone structure // and time `i` in fractional seconds since the UNIX epoch (1970-01-01). // Also returns time zone abbreviation. extern local-utc-deltastd/time/calendar/local-utc-delta: (tz : local-timezone, i : float64) -> (float64, string)( tztz: local-timezone : local-timezonestd/time/calendar/local-timezone: V, ii: float64 : float64std/core/types/float64: V ) : (std/core/types/tuple2: (V, V) -> Vfloat64std/core/types/float64: V,stringstd/core/types/string: V) c "kk_local_get_utc_delta_tuple" cs "_Calendar.LocalUtcDelta" js "_local_utc_delta" /*---------------------------------------------------------------------------- Time and instant conversion using a calendar ----------------------------------------------------------------------------*/ // Return the instant in time for a given `:date` and `:clock` (= `clock0`) interpreted by // calendar `cal` (=`cal-iso`) in a timezone `tz` (=`tz-utc` by default). pub fun date/instantstd/time/calendar/date/instant: (ts : timescale, d : date, c : ? clock, tz : ? timezone, cal : ? calendar) -> instant( tsts: timescale : timescalestd/time/instant/timescale: V, dd: date : datestd/time/date/date: V, cc: ? clock : clockstd/time/date/clock: V = clock0std/time/date/clock0: clock, tztz: ? timezone : timezonestd/time/calendar/timezone: V = tz-utcstd/time/calendar/tz-utc: timezone, calcal: ? calendar : calendarstd/time/calendar/calendar: V = cal-isostd/time/calendar/cal-iso: calendar )result: -> total instant : instantstd/time/instant/instant: V (calcal: calendar.dc-to-instantstd/time/calendar/calendar/dc-to-instant: (calendar : calendar) -> ((date, clock, timezone, timescale) -> instant))( dd: date, cc: clock, tztz: timezone, tsts: timescale ) pub fun utcdate/instantstd/time/calendar/utcdate/instant: (d : date, c : ? clock, tz : ? timezone, cal : ? calendar, ts : ? timescale) -> utc instant( dd: date : datestd/time/date/date: V, cc: ? clock : clockstd/time/date/clock: V = clock0std/time/date/clock0: clock, tztz: ? timezone : timezonestd/time/calendar/timezone: V = tz-utcstd/time/calendar/tz-utc: timezone, calcal: ? calendar : calendarstd/time/calendar/calendar: V = cal-isostd/time/calendar/cal-iso: calendar, tsts: ? timescale : timescalestd/time/instant/timescale: V = utcstd/time/utc/utc: () -> utc timescale() )result: -> utc instant : utcstd/time/utc/utc: (E, V) -> V instantstd/time/instant/instant: V tsts: timescale.instantstd/time/calendar/date/instant: (ts : timescale, d : date, c : ? clock, tz : ? timezone, cal : ? calendar) -> utc instant(dd: date,cc: clock,tztz: timezone,calcal: calendar) // Convert an `:instant` to a `:date`, `:clock`, timezone delta and abbreviation, // for a given timezone `tz` (=`tz-utc` by default) and calendar (=`cal-iso` by default). pub fun instant-dcstd/time/calendar/instant-dc: (i : instant, tz : ? timezone, cal : ? calendar) -> (date, clock, duration, string)( ii: instant : instantstd/time/instant/instant: V, tztz: ? timezone :timezonestd/time/calendar/timezone: V = tz-utcstd/time/calendar/tz-utc: timezone, calcal: ? calendar : calendarstd/time/calendar/calendar: V = cal-isostd/time/calendar/cal-iso: calendar )result: -> total (date, clock, duration, string) : (std/core/types/tuple4: (V, V, V, V) -> Vdatestd/time/date/date: V,clockstd/time/date/clock: V,durationstd/time/duration/duration: V,stringstd/core/types/string: V) //trace("instant-dc: " ++ i.show-raw) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)tzdeltatzdelta: duration,tzabbrvtzabbrv: string)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = (tztz: timezone.utc-deltastd/time/calendar/timezone/utc-delta: (timezone : timezone) -> ((instant) -> (duration, string)))(ii: instant) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)dd: date,cc: clock)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = (calcal: calendar.instant-to-dcstd/time/calendar/calendar/instant-to-dc: (calendar : calendar) -> ((i : instant, tzdelta : duration) -> (date, clock)))( ii: instant, tzdeltatzdelta: duration ) (std/core/types/Tuple4: forall<a,b,c,d> (fst : a, snd : b, thd : c, field4 : d) -> (a, b, c, d)dd: date,cc: clock,tzdeltatzdelta: duration,tzabbrvtzabbrv: string)std/core/types/Tuple4: forall<a,b,c,d> (fst : a, snd : b, thd : c, field4 : d) -> (a, b, c, d) /* Return the instant in time for a given date and clock interpreted by calendar `cal` (=`cal-iso`) in a timezone `tz` (=`tz-utc` by default). The `month`, `day`, `hour`, `minutes` may be outside their usual ranges and will be normalized during the conversion. For example, January 33 converts to February 2. This makes it very easy to add- or subtract days or months to an existing time. When the `seconds` or fraction of seconds `frac` add up over 60 those extra seconds are interpreted as leap seconds. Due to timezone transitions, or leap seconds, it is possible to specify dates that never happened (as it was skipped by a timezone change), or ambigious times (as a timezone springs back). In such cases, the time is always interpreted in the earlier timezone. */ pub fun timescale/instantstd/time/calendar/timescale/instant: (ts : timescale, year : int, month : ? int, day : ? int, hours : ? int, minutes : ? int, seconds : ? int, frac : ? float64, tz : ? timezone, cal : ? calendar) -> instant( tsts: timescale : timescalestd/time/instant/timescale: V, yearyear: int : intstd/core/types/int: V, monthmonth: ? int : intstd/core/types/int: V = 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, dayday: ? int : intstd/core/types/int: V = 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, hourshours: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, minutesminutes: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, secondsseconds: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, fracfrac: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
, tztz: ? timezone : timezonestd/time/calendar/timezone: V = tz-utcstd/time/calendar/tz-utc: timezone, calcal: ? calendar : calendarstd/time/calendar/calendar: V = cal-isostd/time/calendar/cal-iso: calendar )result: -> total instant : instantstd/time/instant/instant: V val fsecsfsecs: ddouble = secondsseconds: int.ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble +std/num/ddouble/(+): (x : ddouble, y : ddouble) -> ddouble fracfrac: float64.ddoublestd/num/ddouble/float64/ddouble: (d : float64) -> ddouble tsts: timescale.instantstd/time/calendar/date/instant: (ts : timescale, d : date, c : ? clock, tz : ? timezone, cal : ? calendar) -> instant( Datestd/time/date/Date: (year : int, month : int, day : int) -> date(yearyear: int,monthmonth: int,dayday: int), Clockstd/time/date/Clock: (hours : int, minutes : int, seconds : ddouble) -> clock(hourshours: int,minutesminutes: int,fsecsfsecs: ddouble), tztz: timezone, calcal: calendar
) pub fun utc/instantstd/time/calendar/utc/instant: (year : int, month : ? int, day : ? int, hours : ? int, minutes : ? int, seconds : ? int, frac : ? float64, tz : ? timezone, cal : ? calendar, ts : ? timescale) -> utc instant( yearyear: int : intstd/core/types/int: V, monthmonth: ? int : intstd/core/types/int: V = 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, dayday: ? int : intstd/core/types/int: V = 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
, hourshours: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, minutesminutes: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, secondsseconds: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, fracfrac: ? float64 : float64std/core/types/float64: V = 0.0literal: float64
hex64= 0x0p+0
, tztz: ? timezone : timezonestd/time/calendar/timezone: V = tz-utcstd/time/calendar/tz-utc: timezone, calcal: ? calendar : calendarstd/time/calendar/calendar: V = cal-isostd/time/calendar/cal-iso: calendar, tsts: ? timescale : timescalestd/time/instant/timescale: V = utcstd/time/utc/utc: () -> utc timescale() )result: -> utc instant : utcstd/time/utc/utc: (E, V) -> V instantstd/time/instant/instant: V tsts: timescale.instantstd/time/calendar/timescale/instant: (ts : timescale, year : int, month : ? int, day : ? int, hours : ? int, minutes : ? int, seconds : ? int, frac : ? float64, tz : ? timezone, cal : ? calendar) -> utc instant(yearyear: int,monthmonth: int,dayday: int,hourshours: int,minutesminutes: int,secondsseconds: int,fracfrac: float64,tztz: timezone,calcal: calendar
) // Return the day of the week for a calendar `cal` (=`cal-iso`). fun weekdaystd/time/calendar/weekday: (d : date, cal : calendar) -> weekday( dd: date : datestd/time/date/date: V, calcal: calendar : calendarstd/time/calendar/calendar: V )result: -> total weekday : weekdaystd/time/date/weekday: V // Generic algorithm for any calendar /* val i = instant(d.year,d.month,d.day,cal=cal) val dow = (i.days+6)%7 // plus 6 since 2000-01-01 epoch was a Saturday (note: 0 = sunday, 1 = monday, ..) */ val daysdays: int = (calcal: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))(dd: date) val dowdow: int = (daysdays: int+std/core/int/(+): (x : int, y : int) -> int6literal: int
dec = 6
hex8 = 0x06
bit8 = 0b00000110
)%std/core/int/(%): (int, int) -> int7literal: int
dec = 7
hex8 = 0x07
bit8 = 0b00000111
// plus 6 since 2000-01-01 epoch was a Saturday (note: 0 = sunday, 1 = monday, ..) dowdow: int.weekdaystd/time/date/weekday: (i : int) -> weekday
// to ISO week day // Return the days between two dates interpreted by calendar `cal`. pub fun days-untilstd/time/calendar/days-until: (cal : calendar, d1 : date, d2 : date) -> int( calcal: calendar : calendarstd/time/calendar/calendar: V, d1d1: date : datestd/time/date/date: V, d2d2: date :datestd/time/date/date: V )result: -> total int : intstd/core/types/int: V val days1days1: int = (calcal: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))(d1d1: date) val days2days2: int = (calcal: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))(d2d2: date) days2days2: int -std/core/int/(-): (x : int, y : int) -> int days1days1: int /* val i1 = instant(d1,cal=cal,ts=ts) val i2 = instant(d2,cal=cal,ts=ts) i2.days - i1.days */ /*---------------------------------------------------------------------------- Earth calendars Abstracts over common patterns to relates dates and time instants to simpler relations between dates and days. ----------------------------------------------------------------------------*/ // Create a calendar where we assume that each // day has 24 hours with 60 minutes, and where minutes are 60 seconds // (with possibly leap seconds). The function takes care of timezones, // epoch shifts, and leap seconds, and only needs a calendar `name`, // a function `days-to-date` to calculate a date given a number of days since the `epoch`, // a function `date-to-days` to calculate days since the `epoch` for a given date, // and an optional time scale to be used (=`ts-utc`).\ // `month-prefix` (=`""`) is used when displaying numeric months and is set for // the ISO week dates to `"W"` for example. The `show-era` function can be given // to display the era of a date. pub fun earth-calendarstd/time/calendar/earth-calendar: (name : string, long-name : string, days-to-date : (days : int) -> date, date-to-days : (date) -> int, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string : stringstd/core/types/string: V, long-namelong-name: string : stringstd/core/types/string: V, days-to-datedays-to-date: (days : int) -> date : (days:intstd/core/types/int: V) -> datestd/time/date/date: V, date-to-daysdate-to-days: (date) -> int : datestd/time/date/date: V -> intstd/core/types/int: V, month-prefixmonth-prefix: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, show-erashow-era: ? ((date) -> string) : (datestd/time/date/date: V)->stringstd/core/types/string: V = fnfn: (d : date) -> string(dd: date){ ""literal: string
count= 0
} // ts : timescale = ts-ti )result: -> total calendar : calendarstd/time/calendar/calendar: V fun instant-to-dcinstant-to-dc: (i : instant, tzdelta : duration) -> (date, clock)(ii: instant : instantstd/time/instant/instant: V, tzdeltatzdelta: duration : durationstd/time/duration/duration: V)result: -> total (date, clock) earth-timestamp-to-dcstd/time/calendar/earth-timestamp-to-dc: (t : timestamp, tzdelta : timespan, days-to-date : (int) -> date) -> (date, clock)( ii: instant.timestampstd/time/instant/instant/timestamp: (i : instant) -> timestamp, tzdeltatzdelta: duration.timespanstd/time/duration/timespan: (d : duration) -> timespan, days-to-datedays-to-date: (days : int) -> date ) fun dc-to-instantdc-to-instant: (d : date, c : clock, tz : timezone, ts : timescale) -> instant(dd: date : datestd/time/date/date: V, cc: clock : clockstd/time/date/clock: V, tztz: timezone : timezonestd/time/calendar/timezone: V, tsts: timescale : timescalestd/time/instant/timescale: V )result: -> total instant earth-timestamp-to-instantstd/time/calendar/earth-timestamp-to-instant: (t : timestamp, tz : timezone, ts : timescale) -> instant( dc-timestampstd/time/calendar/dc-timestamp: (d : date, c : clock, date-to-days : (date) -> int, has-leap-seconds : ? bool) -> timestamp(dd: date, cc: clock, date-to-daysdate-to-days: (date) -> int, tsts: timescale.has-leap-secondsstd/time/instant/has-leap-seconds: (ts : timescale) -> bool), tztz: timezone, tsts: timescale) Calendarstd/time/calendar/Calendar: (name : string, long-name : string, month-prefix : string, show-era : (date) -> string, instant-to-dc : (i : instant, tzdelta : duration) -> (date, clock), dc-to-instant : (date, clock, timezone, timescale) -> instant, days-to-date : (days : int) -> date, date-to-days : (date : date) -> int) -> calendar( namename: string,long-namelong-name: string,month-prefixmonth-prefix: string,show-erashow-era: (date) -> string, instant-to-dcinstant-to-dc: (i : instant, tzdelta : duration) -> (date, clock),dc-to-instantdc-to-instant: (d : date, c : clock, tz : timezone, ts : timescale) -> instant, days-to-datedays-to-date: (days : int) -> date, date-to-daysdate-to-days: (date) -> int
) fun earth-timestamp-to-dcstd/time/calendar/earth-timestamp-to-dc: (t : timestamp, tzdelta : timespan, days-to-date : (int) -> date) -> (date, clock)( tt: timestamp : timestampstd/time/timestamp/timestamp: V, tzdeltatzdelta: timespan: timespanstd/time/timestamp/timespan: V, days-to-datedays-to-date: (int) -> date: (intstd/core/types/int: V) -> datestd/time/date/date: V )result: -> total (date, clock) : (std/core/types/tuple2: (V, V) -> Vdatestd/time/date/date: V,clockstd/time/date/clock: V) // adjust for timezone (disregarding leap seconds for now) (and possibly going into the next or previous day) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)daysdays: int,clockclock: clock)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = (tt: timestamp +std/time/timestamp/(+): (ts : timestamp, t : timespan) -> timestamp tzdeltatzdelta: timespan).days-clockstd/time/timestamp/days-clock: (ts : timestamp) -> (int, clock) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)days-to-datedays-to-date: (int) -> date(daysdays: int),clockclock: clock)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) fun earth-timestamp-to-instantstd/time/calendar/earth-timestamp-to-instant: (t : timestamp, tz : timezone, ts : timescale) -> instant( tt: timestamp : timestampstd/time/timestamp/timestamp: V, tztz: timezone : timezonestd/time/calendar/timezone: V, tsts: timescale : timescalestd/time/instant/timescale: V )result: -> total instant : instantstd/time/instant/instant: V // do timezone adjustment ignoring leap seconds (TODO: check correctness) val ii: instant = tsts: timescale.instantstd/time/instant/timescale/instant: (ts : timescale, t : timestamp) -> instant(tt: timestamp) val iziz: instant = if tztz: timezone.is-tz-utcstd/time/calendar/is-tz-utc: (tz : timezone) -> bool then ii: instant else match((tztz: timezone.utc-inversestd/time/calendar/timezone/utc-inverse: (timezone : timezone) -> ((instant) -> maybe<instant>))(ii: instant)) Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(invinv: instant) -> invinv: instant Nothingstd/core/types/Nothing: forall<a> maybe<a> -> // no explicit inverse, // do a double pass to accommodate jumping over a DST boundary. val tzd1tzd1: duration = (tztz: timezone.utc-deltastd/time/calendar/timezone/utc-delta: (timezone : timezone) -> ((instant) -> (duration, string)))(ii: instant).fststd/core/types/tuple2/fst: (tuple2 : (duration, string)) -> duration val tzi1tzi1: instant = tsts: timescale.instantstd/time/instant/timescale/instant: (ts : timescale, t : timestamp) -> instant(tt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tzd1tzd1: duration.timespanstd/time/duration/timespan: (d : duration) -> timespan) val tzd2tzd2: duration = (tztz: timezone.utc-deltastd/time/calendar/timezone/utc-delta: (timezone : timezone) -> ((instant) -> (duration, string)))(tzi1tzi1: instant).fststd/core/types/tuple2/fst: (tuple2 : (duration, string)) -> duration if tzd1tzd1: duration==std/time/duration/(==): (i : duration, j : duration) -> booltzd2tzd2: duration then tzi1tzi1: instant else tsts: timescale.instantstd/time/instant/timescale/instant: (ts : timescale, t : timestamp) -> instant(tt: timestamp -std/time/timestamp/(-): (ts : timestamp, t : timespan) -> timestamp tzd2tzd2: duration.timespanstd/time/duration/timespan: (d : duration) -> timespan) iziz: instant pub fun cal-timestampstd/time/calendar/cal-timestamp: (cal : calendar, ts : timescale, d : date, c : clock) -> timestamp( calcal: calendar : calendarstd/time/calendar/calendar: V, tsts: timescale : timescalestd/time/instant/timescale: V, dd: date : datestd/time/date/date: V, cc: clock : clockstd/time/date/clock: V )result: -> total timestamp : timestampstd/time/timestamp/timestamp: V dc-timestampstd/time/calendar/dc-timestamp: (d : date, c : clock, date-to-days : (date) -> int, has-leap-seconds : ? bool) -> timestamp(dd: date,cc: clock,calcal: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int),tsts: timescale.has-leap-secondsstd/time/instant/has-leap-seconds: (ts : timescale) -> bool) fun dc-timestampstd/time/calendar/dc-timestamp: (d : date, c : clock, date-to-days : (date) -> int, has-leap-seconds : ? bool) -> timestamp( dd: date : datestd/time/date/date: V, cc: clock : clockstd/time/date/clock: V, date-to-daysdate-to-days: (date) -> int: (datestd/time/date/date: V) -> intstd/core/types/int: V, has-leap-secondshas-leap-seconds: ? bool : boolstd/core/types/bool: V = Falsestd/core/types/False: bool)result: -> total timestamp : timestampstd/time/timestamp/timestamp: V // check if we are in a leap second and remember val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)xsecsxsecs: ddouble,leapleap: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = if !std/core/types/bool/(!): (b : bool) -> boolhas-leap-secondshas-leap-seconds: bool ||std/core/types/(||): (x : bool, y : bool) -> bool cc: clock.secondsstd/time/date/clock/seconds: (clock : clock) -> ddouble <std/num/ddouble/(<): (x : ddouble, y : ddouble) -> bool 60literal: int
dec = 60
hex8 = 0x3C
bit8 = 0b00111100
.ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble then (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cc: clock.secondsstd/time/date/clock/seconds: (clock : clock) -> ddouble,0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) else val leapleap: int = cc: clock.secondsstd/time/date/clock/seconds: (clock : clock) -> ddouble.floorstd/num/ddouble/floor: (x : ddouble) -> ddouble.intstd/num/ddouble/int: (x : ddouble, nonfin : ? int) -> int -std/core/int/(-): (x : int, y : int) -> int 59literal: int
dec = 59
hex8 = 0x3B
bit8 = 0b00111011
(std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cc: clock.secondsstd/time/date/clock/seconds: (clock : clock) -> ddouble -std/num/ddouble/(-): (x : ddouble, y : ddouble) -> ddouble leapleap: int.ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble, leapleap: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) val secssecs: ddouble = (((cc: clock.hoursstd/time/date/clock/hours: (clock : clock) -> int*std/core/int/(*): (int, int) -> int60literal: int
dec = 60
hex8 = 0x3C
bit8 = 0b00111100
) +std/core/int/(+): (x : int, y : int) -> int cc: clock.minutesstd/time/date/clock/minutes: (clock : clock) -> int)*std/core/int/(*): (int, int) -> int60literal: int
dec = 60
hex8 = 0x3C
bit8 = 0b00111100
).ddoublestd/num/ddouble/int/ddouble: (i : int) -> ddouble +std/num/ddouble/(+): (x : ddouble, y : ddouble) -> ddouble xsecsxsecs: ddouble val daysdays: int = date-to-daysdate-to-days: (date) -> int( dd: date ) timestamp-daysstd/time/timestamp/timestamp-days: (days : int, secs : ? timespan, leap : ? int) -> timestamp(daysdays: int,secssecs: ddouble,leapleap: int
) /*---------------------------------------------------------------------------- Combine earth calendars/ year-shift earth calendars ----------------------------------------------------------------------------*/ // Create a new calendar from by combining two other calendars. The `switch-date` // is in terms of the second calendar (`cal2`) and time after (and including) the switch // date is displayed in `cal2` while times before it in `cal1`. This function is used // for example for the Julian Gregorian calendar. pub fun combine-earth-calendarsstd/time/calendar/combine-earth-calendars: (name : string, long-name : string, switch-date : date, cal1 : calendar, cal2 : calendar, mb-show-era : ? (maybe<(date) -> string>)) -> calendar( namename: string : stringstd/core/types/string: V, long-namelong-name: string : stringstd/core/types/string: V, switch-dateswitch-date: date : datestd/time/date/date: V, cal1cal1: calendar : calendarstd/time/calendar/calendar: V, cal2cal2: calendar : calendarstd/time/calendar/calendar: V, mb-show-eramb-show-era: ? (maybe<(date) -> string>) : maybestd/core/types/maybe: V -> V<(datestd/time/date/date: V) -> stringstd/core/types/string: V> = Nothingstd/core/types/Nothing: forall<a> maybe<a> )result: -> total calendar : calendarstd/time/calendar/calendar: V val switch-daysswitch-days: int = (cal2cal2: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))(switch-dateswitch-date: date) //+ skip fun cdays-to-datecdays-to-date: (days : int) -> date( daysdays: int : intstd/core/types/int: V )result: -> total date : datestd/time/date/date: V ((if daysdays: int <std/core/int/(<): (x : int, y : int) -> bool switch-daysswitch-days: int then cal1cal1: calendar else cal2cal2: calendar).days-to-datestd/time/calendar/calendar/days-to-date: (calendar : calendar) -> ((days : int) -> date))(daysdays: int) fun cdate-to-dayscdate-to-days: (d : date) -> int( dd: date : datestd/time/date/date: V )result: -> total int : intstd/core/types/int: V ((if dd: date <std/time/date/(<): (i : date, j : date) -> bool switch-dateswitch-date: date then cal1cal1: calendar else cal2cal2: calendar).date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))(dd: date) fun cshow-eracshow-era: (d : date) -> string(dd: date : datestd/time/date/date: V )result: -> total string : stringstd/core/types/string: V match mb-show-eramb-show-era: maybe<(date) -> string> Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(showerashowera: (date) -> string) -> dd: date.showerashowera: (date) -> string Nothingstd/core/types/Nothing: forall<a> maybe<a> -> ((if dd: date <std/time/date/(<): (i : date, j : date) -> bool switch-dateswitch-date: date then cal1cal1: calendar else cal2cal2: calendar).show-erastd/time/calendar/calendar/show-era: (calendar : calendar) -> ((date) -> string))(dd: date) earth-calendarstd/time/calendar/earth-calendar: (name : string, long-name : string, days-to-date : (days : int) -> date, date-to-days : (date) -> int, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string, long-namelong-name: string, cdays-to-datecdays-to-date: (days : int) -> date, cdate-to-dayscdate-to-days: (d : date) -> int, show-era = cshow-eracshow-era: (d : date) -> string ) // Create a new calendar from anoter calendar `cal` by adding an offset to the // years (`year-shift`). This is used for example to create the Ethiopian calendar // from the Coptic calendar, by using: // `year-shift-earth-calendar( "EC", "Ethiopian", ~276, cal-coptic )` pub fun year-shift-earth-calendarstd/time/calendar/year-shift-earth-calendar: (name : string, long-name : string, year-shift : int, cal : calendar, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string : stringstd/core/types/string: V, long-namelong-name: string: stringstd/core/types/string: V, year-shiftyear-shift: int : intstd/core/types/int: V, calcal: calendar : calendarstd/time/calendar/calendar: V, month-prefixmonth-prefix: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, show-erashow-era: ? ((date) -> string) : (datestd/time/date/date: V)->stringstd/core/types/string: V = fnfn: (d : date) -> string(dd: date){ ""literal: string
count= 0
} )result: -> total calendar : calendarstd/time/calendar/calendar: V fun shift-days-to-dateshift-days-to-date: (days : int) -> date( daysdays: int : intstd/core/types/int: V )result: -> total date : datestd/time/date/date: V val dd: date = (calcal: calendar.days-to-datestd/time/calendar/calendar/days-to-date: (calendar : calendar) -> ((days : int) -> date))(daysdays: int) dd: date(year = dd: date.yearstd/time/date/date/year: (date : date) -> int -std/core/int/(-): (x : int, y : int) -> int year-shiftyear-shift: int) fun shift-date-to-daysshift-date-to-days: (d : date) -> int( dd: date : datestd/time/date/date: V )result: -> total int : intstd/core/types/int: V (calcal: calendar.date-to-daysstd/time/calendar/calendar/date-to-days: (calendar : calendar) -> ((date : date) -> int))( dd: date(year = dd: date.yearstd/time/date/date/year: (date : date) -> int +std/core/int/(+): (x : int, y : int) -> int year-shiftyear-shift: int) ) earth-calendarstd/time/calendar/earth-calendar: (name : string, long-name : string, days-to-date : (days : int) -> date, date-to-days : (date) -> int, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string, long-namelong-name: string, shift-days-to-dateshift-days-to-date: (days : int) -> date, shift-date-to-daysshift-date-to-days: (d : date) -> int, month-prefixmonth-prefix: string, show-erashow-era: (date) -> string
) /*---------------------------------------------------------------------------- Generic solar calendars: Abstract over almost all calendars that work in terms of months and solar years. ----------------------------------------------------------------------------*/ // An abstraction over solar calendars. Almost all calendars can be defined // in terms of this function (and `solar-ecalendar`). Given functions to // convert days to and from a year, and day-of-the-year to and from month // and month day, this constructs a full calendar.\ // Also needs an `epoch-shift` that gives the number of days from the // calendar epoch to the date ``2000-01-01``. By default this is `730119` // which corresponds to a ``0001-01-01`` ISO calendar epoch. The // `has-year-zero` (=`True`) parameter is used when the calendar has a // year zero. The `month-prefix` (=`""`) is used for displaying numeric // months (and is `"W"` for `cal-iso-week` for example). The `show-era` function // can be given to display an era for a given date. Finally the `ts` (=`ts-ti`) // gives the time scale for the calendar. pub fun solar-calendarstd/time/calendar/solar-calendar: (name : string, long-name : string, days-before-year : (year : int) -> int, days-to-yeardoy : (days : int) -> (int, int), days-before-month : (year : int, month : int) -> int, days-to-month : (year : int, doy : int) -> int, epoch-shift : ? int, has-year-zero : ? bool, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string : stringstd/core/types/string: V, long-namelong-name: string: stringstd/core/types/string: V, days-before-yeardays-before-year: (year : int) -> int : (year:intstd/core/types/int: V) -> intstd/core/types/int: V, days-to-yeardoydays-to-yeardoy: (days : int) -> (int, int) : (days:intstd/core/types/int: V) -> (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,intstd/core/types/int: V), days-before-monthdays-before-month: (year : int, month : int) -> int: (year:intstd/core/types/int: V, month:intstd/core/types/int: V) -> intstd/core/types/int: V, days-to-monthdays-to-month: (year : int, doy : int) -> int : (year:intstd/core/types/int: V, doy: intstd/core/types/int: V ) -> intstd/core/types/int: V, epoch-shiftepoch-shift: ? int : intstd/core/types/int: V = 730119literal: int
dec = 730119
hex32= 0x000B2407
bit32= 0b00000000000010110010010000000111
, has-year-zerohas-year-zero: ? bool : boolstd/core/types/bool: V = Truestd/core/types/True: bool, month-prefixmonth-prefix: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, show-erashow-era: ? ((date) -> string) : (datestd/time/date/date: V)->stringstd/core/types/string: V = fnfn: (d : date) -> string(dd: date){ ""literal: string
count= 0
} )result: -> total calendar : calendarstd/time/calendar/calendar: V fun date-to-daysdate-to-days: (d : date) -> int( dd: date : datestd/time/date/date: V )result: -> total int : intstd/core/types/int: V val yy: int = if has-year-zerohas-year-zero: bool ||std/core/types/(||): (x : bool, y : bool) -> bool dd: date.yearstd/time/date/date/year: (date : date) -> int.is-posstd/core/int/is-pos: (i : int) -> bool then dd: date.yearstd/time/date/date/year: (date : date) -> int else dd: date.yearstd/time/date/date/year: (date : date) -> int.incstd/core/int/inc: (i : int) -> int days-before-yeardays-before-year: (year : int) -> int( yy: int ) +std/core/int/(+): (x : int, y : int) -> int days-before-monthdays-before-month: (year : int, month : int) -> int( yy: int, dd: date.monthstd/time/date/date/month: (date : date) -> int ) +std/core/int/(+): (x : int, y : int) -> int dd: date.daystd/time/date/date/day: (date : date) -> int.decstd/core/int/dec: (i : int) -> int -std/core/int/(-): (x : int, y : int) -> int epoch-shiftepoch-shift: int fun days-to-datedays-to-date: (days0 : int) -> date( days0days0: int : intstd/core/types/int: V )result: -> total date : datestd/time/date/date: V val daysdays: int = days0days0: int +std/core/int/(+): (x : int, y : int) -> int epoch-shiftepoch-shift: int val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)yy: int,doydoy: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = days-to-yeardoydays-to-yeardoy: (days : int) -> (int, int)( daysdays: int ) val monthmonth: int = days-to-monthdays-to-month: (year : int, doy : int) -> int(yy: int, doydoy: int) val dayday: int = (doydoy: int -std/core/int/(-): (x : int, y : int) -> int days-before-monthdays-before-month: (year : int, month : int) -> int(yy: int, monthmonth: int)) +std/core/int/(+): (x : int, y : int) -> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
val yearyear: int = if has-year-zerohas-year-zero: bool ||std/core/types/(||): (x : bool, y : bool) -> bool yy: int.is-posstd/core/int/is-pos: (i : int) -> bool then yy: int else yy: int.decstd/core/int/dec: (i : int) -> int Datestd/time/date/Date: (year : int, month : int, day : int) -> date(yearyear: int,monthmonth: int,dayday: int
) earth-calendarstd/time/calendar/earth-calendar: (name : string, long-name : string, days-to-date : (days : int) -> date, date-to-days : (date) -> int, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string, long-namelong-name: string, days-to-datedays-to-date: (days0 : int) -> date, date-to-daysdate-to-days: (d : date) -> int, month-prefixmonth-prefix: string, show-erashow-era: (date) -> string
) // An abstraction over solar calendars. Almost all calendars can be defined // in terms of this function (and `solar-calendar`). Given functions to // convert days to and from a year, and day-of-the-year to and from month // and month day, this constructs a full calendar. In contrast to `solar-calendar` // this function just needs an estimation function from days to a year -- for most // calendars this is much more convenient. The estimation function returns a // conservative (i.e. lowest) estimate for the year and a `maybe<int>` that // is the `safe-day`: if the day of the year is lower or equal to that the estimate // is surely correct. Otherwise the wrapper will calculate the start day for the next // year until the correct year is found.\ // Also needs an `epoch-shift` that gives the number of days from the // calendar epoch to the date ``2000-01-01``. By default this is `730119` // which corresponds to a ``0001-01-01`` ISO calendar epoch. The // `has-year-zero` (=`True`) parameter is used when the calendar has a // year zero. The `month-prefix` (=`""`) is used for displaying numeric // months (and is `"W"` for `cal-iso-week` for example). The `show-era` function // can be given to display an era for a given date. Finally the `ts` (=`ts-utc`) // gives the time scale for the calendar. pub fun solar-ecalendarstd/time/calendar/solar-ecalendar: (name : string, long-name : string, days-before-year : (year : int) -> int, estimate-year : (days : int) -> (int, maybe<int>), days-before-month : (year : int, month : int) -> int, days-to-month : (year : int, doy : int) -> int, epoch-shift : ? int, has-year-zero : ? bool, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string : stringstd/core/types/string: V, long-namelong-name: string: stringstd/core/types/string: V, days-before-yeardays-before-year: (year : int) -> int : (year:intstd/core/types/int: V) -> intstd/core/types/int: V, estimate-yearestimate-year: (days : int) -> (int, maybe<int>) : (days:intstd/core/types/int: V) -> (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,maybestd/core/types/maybe: V -> V<intstd/core/types/int: V>), days-before-monthdays-before-month: (year : int, month : int) -> int: (year:intstd/core/types/int: V, month:intstd/core/types/int: V) -> intstd/core/types/int: V, days-to-monthdays-to-month: (year : int, doy : int) -> int : (year:intstd/core/types/int: V, doy: intstd/core/types/int: V ) -> intstd/core/types/int: V, epoch-shiftepoch-shift: ? int : intstd/core/types/int: V = 730119literal: int
dec = 730119
hex32= 0x000B2407
bit32= 0b00000000000010110010010000000111
, has-year-zerohas-year-zero: ? bool : boolstd/core/types/bool: V = Truestd/core/types/True: bool, month-prefixmonth-prefix: ? string : stringstd/core/types/string: V = ""literal: string
count= 0
, show-erashow-era: ? ((date) -> string) : (datestd/time/date/date: V)->stringstd/core/types/string: V = fnfn: (d : date) -> string(dd: date){ ""literal: string
count= 0
} )result: -> total calendar : calendarstd/time/calendar/calendar: V fun days-to-yeardoydays-to-yeardoy: (days : int) -> (int, int)(daysdays: int:intstd/core/types/int: V)result: -> total (int, int) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,intstd/core/types/int: V) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)approxapprox: int,safesafe: maybe<int>)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = estimate-yearestimate-year: (days : int) -> (int, maybe<int>)(daysdays: int) val doy1doy1: int = daysdays: int -std/core/int/(-): (x : int, y : int) -> int days-before-yeardays-before-year: (year : int) -> int(approxapprox: int) if (doy1doy1: int <=std/core/int/(<=): (x : int, y : int) -> bool safesafe: maybe<int>.defaultstd/core/maybe/default: (m : maybe<int>, nothing : int) -> int(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)) then returnreturn: (int, int) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)approxapprox: int,doy1doy1: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) val doy2doy2: int = daysdays: int -std/core/int/(-): (x : int, y : int) -> int days-before-yeardays-before-year: (year : int) -> int(approxapprox: int.incstd/core/int/inc: (i : int) -> int) if doy2doy2: int <std/core/int/(<): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)approxapprox: int,doy1doy1: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) else (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)approxapprox: int.incstd/core/int/inc: (i : int) -> int, doy2doy2: int
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) solar-calendarstd/time/calendar/solar-calendar: (name : string, long-name : string, days-before-year : (year : int) -> int, days-to-yeardoy : (days : int) -> (int, int), days-before-month : (year : int, month : int) -> int, days-to-month : (year : int, doy : int) -> int, epoch-shift : ? int, has-year-zero : ? bool, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar(namename: string,long-namelong-name: string, days-before-yeardays-before-year: (year : int) -> int, days-to-yeardoydays-to-yeardoy: (days : int) -> (int, int), days-before-monthdays-before-month: (year : int, month : int) -> int, days-to-monthdays-to-month: (year : int, doy : int) -> int, epoch-shiftepoch-shift: int, has-year-zerohas-year-zero: bool, month-prefixmonth-prefix: string, show-erashow-era: (date) -> string
) // ---------------------------------------------------- // ISO calendar: // We define it here (instead of std/time/calendars) because it is the default calendar. // ---------------------------------------------------- // Create a standard ISO calendar using a particular time scale // and calendar `name` (=`ts.name`). pub fun iso-calendarstd/time/calendar/iso-calendar: (timescale, name : string, long-name : ? string) -> calendar( _ts : timescalestd/time/instant/timescale: V, namename: string : stringstd/core/types/string: V, long-namelong-name: ? string : stringstd/core/types/string: V = namename: string )result: -> total calendar : calendarstd/time/calendar/calendar: V solar-ecalendarstd/time/calendar/solar-ecalendar: (name : string, long-name : string, days-before-year : (year : int) -> int, estimate-year : (days : int) -> (int, maybe<int>), days-before-month : (year : int, month : int) -> int, days-to-month : (year : int, doy : int) -> int, epoch-shift : ? int, has-year-zero : ? bool, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( namename: string, long-namelong-name: string, iso-days-before-yearstd/time/calendar/iso-days-before-year: (year : int) -> int, iso-estimate-yearstd/time/calendar/iso-estimate-year: (days : int) -> (int, maybe<int>), iso-days-before-monthstd/time/calendar/iso-days-before-month: (year : int, month : int) -> int, iso-doy-to-monthstd/time/calendar/iso-doy-to-month: (year : int, doy : int) -> int ) // The standard [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) calendar // using TI time (`ts-ti`). This is a proleptic Gregorian // calendar except that it uses the year 0 for 1 BCE, -1 for 2 BCE etc. // // This is the default calendar used in the library as it guarantees deterministic // date calculations while still taking historical leap seconds into account. pub val cal-isostd/time/calendar/cal-iso: calendar = iso-calendarstd/time/calendar/iso-calendar: (timescale, name : string, long-name : ? string) -> calendar( ts-tistd/time/utc/ts-ti: timescale, ""literal: string
count= 0
, "ISO"literal: string
count= 3
) // Create a standard [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) calendar // using UTC time (`ts-utc-create`) given a provide leap second table (`:leaps-table`). // This is a proleptic Gregorian // calendar except that it uses the year 0 for 1 BCE, -1 for 2 BCE etc. // // You can create an ISO 8601 UTC calendar using the latest IERS leap // second data using [`cal-utc-load`](std_time_download.html#cal_utc_load). pub fun cal-utc-createstd/time/calendar/cal-utc-create: (leaps : leaps-table) -> calendar( leapsleaps: leaps-table : leaps-tablestd/time/utc/leaps-table: V )result: -> total calendar : calendarstd/time/calendar/calendar: V val ts-utcts-utc: timescale = ts-utc-createstd/time/utc/ts-utc-create: (leaps : leaps-table) -> timescale(leapsleaps: leaps-table) iso-calendarstd/time/calendar/iso-calendar: (timescale, name : string, long-name : ? string) -> calendar( ts-utcts-utc: timescale, ""literal: string
count= 0
, "ISO"literal: string
count= 3
) /* The standard [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) calendar but using TI-SLS time (`ts-ti-sls`), i.e. TI with [smoothed leap seconds](https://www.cl.cam.ac.uk/~mgk25/time/utc-sls/). This calendar is equivalent to the ISO calendar except for the last 1000 seconds of a day where a leap second occurs. On such day, the leap second time step (positive or negative) is distributed over the last 1000 seconds of the day. On the full hour, ISO and ISO-SLS are equal again. This is a recommended calendar to use for time stamps or communication with other services since it avoids any potential trouble with leap seconds while still being quite precise. Other good properties include: - All days have 86400 seconds, and the time 23:59:60 never appears - The time never differs more than one second from UTC - Time as always equal to UTC on the full and half hour */ pub val cal-iso-slsstd/time/calendar/cal-iso-sls: calendar = iso-calendarstd/time/calendar/iso-calendar: (timescale, name : string, long-name : ? string) -> calendar( ts-ti-slsstd/time/utc/ts-ti-sls: timescale, "SLS"literal: string
count= 3
, "ISO-SLS"literal: string
count= 7
) // Create a new ISO 8601 calendar based on UTC-SLS time, i.e. UTC with smoothed leap // seconds. pub fun cal-utc-sls-createstd/time/calendar/cal-utc-sls-create: (leaps : leaps-table) -> calendar( leapsleaps: leaps-table : leaps-tablestd/time/utc/leaps-table: V )result: -> total calendar : calendarstd/time/calendar/calendar: V val ts-utc-slsts-utc-sls: timescale = ts-utc-sls-createstd/time/utc/ts-utc-sls-create: (leaps : leaps-table) -> timescale(leapsleaps: leaps-table) iso-calendarstd/time/calendar/iso-calendar: (timescale, name : string, long-name : ? string) -> calendar( ts-utc-slsts-utc-sls: timescale, "SLS"literal: string
count= 3
, "ISO-SLS"literal: string
count= 7
) // The (proleptic) [Gregorian calendar](https://en.wikipedia.org/wiki/Gregorian_calendar). // Just like the ISO calendar except that the year 0 does not exist, i.e. after 1 BCE (=`~1`) // we have 1 CE (=`1`). // The calendar short name is ``GC``. pub val cal-gregorianstd/time/calendar/cal-gregorian: calendar = solar-ecalendarstd/time/calendar/solar-ecalendar: (name : string, long-name : string, days-before-year : (year : int) -> int, estimate-year : (days : int) -> (int, maybe<int>), days-before-month : (year : int, month : int) -> int, days-to-month : (year : int, doy : int) -> int, epoch-shift : ? int, has-year-zero : ? bool, month-prefix : ? string, show-era : ? ((date) -> string)) -> calendar( "GC"literal: string
count= 2
, "Gregorian"literal: string
count= 9
, iso-days-before-yearstd/time/calendar/iso-days-before-year: (year : int) -> int, iso-estimate-yearstd/time/calendar/iso-estimate-year: (days : int) -> (int, maybe<int>), iso-days-before-monthstd/time/calendar/iso-days-before-month: (year : int, month : int) -> int, iso-doy-to-monthstd/time/calendar/iso-doy-to-month: (year : int, doy : int) -> int, has-year-zero = Falsestd/core/types/False: bool, show-era = fnfn: (d : date) -> string(dd: date:datestd/time/date/date: V){ if dd: date.yearstd/time/date/date/year: (date : date) -> int.is-negstd/core/int/is-neg: (i : int) -> bool then "BCE"literal: string
count= 3
else "CE"literal: string
count= 2
}
) fun iso-days-before-monthstd/time/calendar/iso-days-before-month: (year : int, month : int) -> int( yearyear: int : intstd/core/types/int: V, monthmonth: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V val adjadj: int = iso-adjuststd/time/calendar/iso-adjust: (is-before-march : bool, year : int) -> int( monthmonth: int<=std/core/int/(<=): (x : int, y : int) -> bool2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
, yearyear: int ) (367literal: int
dec = 367
hex16= 0x016F
bit16= 0b0000000101101111
*std/core/int/(*): (int, int) -> intmonthmonth: int -std/core/int/(-): (x : int, y : int) -> int 362literal: int
dec = 362
hex16= 0x016A
bit16= 0b0000000101101010
)/std/core/int/(/): (x : int, y : int) -> int12literal: int
dec = 12
hex8 = 0x0C
bit8 = 0b00001100
-std/core/int/(-): (x : int, y : int) -> int adjadj: int
fun iso-doy-to-monthstd/time/calendar/iso-doy-to-month: (year : int, doy : int) -> int( yearyear: int : intstd/core/types/int: V, doydoy: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V val adjadj: int = iso-adjuststd/time/calendar/iso-adjust: (is-before-march : bool, year : int) -> int( doydoy: int<=std/core/int/(<=): (x : int, y : int) -> bool58literal: int
dec = 58
hex8 = 0x3A
bit8 = 0b00111010
, yearyear: int) (12literal: int
dec = 12
hex8 = 0x0C
bit8 = 0b00001100
*std/core/int/(*): (int, int) -> int(doydoy: int +std/core/int/(+): (x : int, y : int) -> int adjadj: int) +std/core/int/(+): (x : int, y : int) -> int 373literal: int
dec = 373
hex16= 0x0175
bit16= 0b0000000101110101
)/std/core/int/(/): (x : int, y : int) -> int367literal: int
dec = 367
hex16= 0x016F
bit16= 0b0000000101101111
fun iso-adjuststd/time/calendar/iso-adjust: (is-before-march : bool, year : int) -> int( is-before-marchis-before-march: bool : boolstd/core/types/bool: V, yearyear: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V if is-before-marchis-before-march: bool then 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
elif (iso-is-leapstd/time/calendar/iso-is-leap: (year : int) -> bool(yearyear: int)) then 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
else
2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
fun iso-is-leapstd/time/calendar/iso-is-leap: (year : int) -> bool( yearyear: int : intstd/core/types/int: V )result: -> total bool (yearyear: int%std/core/int/(%): (int, int) -> int4literal: int
dec = 4
hex8 = 0x04
bit8 = 0b00000100
==std/core/int/(==): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
) &&std/core/types/(&&): (x : bool, y : bool) -> bool (yearyear: int%std/core/int/(%): (int, int) -> int100literal: int
dec = 100
hex8 = 0x64
bit8 = 0b01100100
!=std/core/int/(!=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
||std/core/types/(||): (x : bool, y : bool) -> bool yearyear: int%std/core/int/(%): (int, int) -> int400literal: int
dec = 400
hex16= 0x0190
bit16= 0b0000000110010000
==std/core/int/(==): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
) fun iso-days-before-yearstd/time/calendar/iso-days-before-year: (year : int) -> int( yearyear: int : intstd/core/types/int: V )result: -> total int val yy: int = yearyear: int.decstd/core/int/dec: (i : int) -> int val leapdaysleapdays: int = (yy: int/std/core/int/(/): (x : int, y : int) -> int4literal: int
dec = 4
hex8 = 0x04
bit8 = 0b00000100
-std/core/int/(-): (x : int, y : int) -> int yy: int/std/core/int/(/): (x : int, y : int) -> int100literal: int
dec = 100
hex8 = 0x64
bit8 = 0b01100100
) +std/core/int/(+): (x : int, y : int) -> int yy: int/std/core/int/(/): (x : int, y : int) -> int400literal: int
dec = 400
hex16= 0x0190
bit16= 0b0000000110010000
365literal: int
dec = 365
hex16= 0x016D
bit16= 0b0000000101101101
*std/core/int/(*): (int, int) -> intyy: int +std/core/int/(+): (x : int, y : int) -> int leapdaysleapdays: int
fun iso-estimate-yearstd/time/calendar/iso-estimate-year: (days : int) -> (int, maybe<int>)( daysdays: int : intstd/core/types/int: V )result: -> total (int, maybe<int>) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,maybestd/core/types/maybe: V -> V<intstd/core/types/int: V>) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)eraera: int,yoeyoe: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = divmodstd/core/int/divmod: (x : int, y : int) -> (int, int)(daysdays: int,146097literal: int
dec = 146097
hex32= 0x00023AB1
bit32= 0b00000000000000100011101010110001
) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
+std/core/int/(+): (x : int, y : int) -> int 400literal: int
dec = 400
hex16= 0x0190
bit16= 0b0000000110010000
*std/core/int/(*): (int, int) -> interaera: int +std/core/int/(+): (x : int, y : int) -> int (100literal: int
dec = 100
hex8 = 0x64
bit8 = 0b01100100
*std/core/int/(*): (int, int) -> intyoeyoe: int)/std/core/int/(/): (x : int, y : int) -> int36525literal: int
dec = 36525
hex32= 0x00008EAD
bit32= 0b00000000000000001000111010101101
, Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(363literal: int
dec = 363
hex16= 0x016B
bit16= 0b0000000101101011
)
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)