diff --git a/timedesc/Timedesc/Interval/index.html b/timedesc/Timedesc/Interval/index.html index 9f762779..7d2bc924 100644 --- a/timedesc/Timedesc/Interval/index.html +++ b/timedesc/Timedesc/Interval/index.html @@ -8,7 +8,7 @@ unit

Pretty printing for interval.

Default format string:

[{syear} {smon:Xxx} {sday:0X} {shour:0X}:{smin:0X}:{ssec:0X}{ssec-frac:.} \
 {stzoff-sign}{stzoff-hour:0X}:{stzoff-min:0X}:{stzoff-sec:0X}, {eyear} \
 {emon:Xxx} {eday:0X} {ehour:0X}:{emin:0X}:{esec:0X}{esec-frac:.} \
-{etzoff-sign}{etzoff-hour:0X}:{etzoff-min:0X}:{etzoff-sec:0X})

Follows same format string rules as Date_time.to_string, but tags are prefixed with 's' for "start time", and 'e' for "end exc time", e.g. for interval (x, y)

val to_string : ?display_using_tz:Time_zone.t -> ?format:string -> t -> string
val pp_seq : +{etzoff-sign}{etzoff-hour:0X}:{etzoff-min:0X}:{etzoff-sec:0X})

Follows same format string rules as pp, but tags are prefixed with 's' for "start time", and 'e' for "end exc time", e.g. for interval (x, y)

  • {syear} gives year of the x
  • {ehour:cX} gives hour of the y
val to_string : ?display_using_tz:Time_zone.t -> ?format:string -> t -> string
val pp_seq : ?display_using_tz:Time_zone.t -> ?format:string -> ?sep:(Stdlib.Format.formatter -> unit -> unit) -> diff --git a/timedesc/Timedesc/Utils/index.html b/timedesc/Timedesc/Utils/index.html index a62d7f3b..995f0b9d 100644 --- a/timedesc/Timedesc/Utils/index.html +++ b/timedesc/Timedesc/Utils/index.html @@ -1,3 +1,2 @@ -Utils (timedesc.Timedesc.Utils)

Module Timedesc.Utils

val ptime_span_of_span : Span.t -> Ptime.span option
val ptime_of_timestamp : timestamp -> Ptime.t option
val span_of_ptime_span : Ptime.span -> Span.t

Warning: Subnanosecond information is lost in this conversion

val timestamp_of_ptime : Ptime.t -> timestamp

Warning: Subnanosecond information is lost in this conversion

val day_count_of_year : year:int -> int
val day_count_of_month : year:int -> month:int -> int
val week_count_of_iso_year : year:int -> int

Month utils

type month = [
  1. | `Jan
  2. | `Feb
  3. | `Mar
  4. | `Apr
  5. | `May
  6. | `Jun
  7. | `Jul
  8. | `Aug
  9. | `Sep
  10. | `Oct
  11. | `Nov
  12. | `Dec
]
val human_int_of_month : month -> int

This yields the usual human readable numbering of 1 to 12 inclusive

val index_of_month : month -> int

This yields the index based numbering of 0 to 11 inclusive

val month_of_human_int : int -> month option
val month_of_index : int -> month option
val weekday_of_tm_int : int -> weekday option
val tm_int_of_weekday : weekday -> int
val weekday_of_iso_int : int -> weekday option
val iso_int_of_weekday : weekday -> int
val get_local_tz_for_arg : unit -> Time_zone.t
val abbr_string_of_weekday : weekday -> string

Warning: Following functions are direct applications of the relevant formulas with little to no error checking.

You are advised to read the source code of the following functions in

date_time_utils.ml} if you intend to use them
-                                                                               to ensure they behave as you expect.
val is_leap_year : year:int -> bool
val jd_of_ymd : year:int -> month:int -> day:int -> int
val jd_of_ydoy : year:int -> day_of_year:int -> int
val jd_of_date : Date.t -> int
val jd_of_unix_epoch : int
val jd_span_of_unix_epoch : Span.t
val jd_of_iso_week_date : year:int -> week:int -> weekday:weekday -> int
val ymd_of_jd : int -> int * int * int
val weekday_of_jd : int -> weekday
val iso_week_date_of_jd : int -> int * int * weekday
val doy_of_ymd : year:int -> month:int -> day:int -> int
+Utils (timedesc.Timedesc.Utils)

Module Timedesc.Utils

val ptime_span_of_span : Span.t -> Ptime.span option
val ptime_of_timestamp : timestamp -> Ptime.t option
val span_of_ptime_span : Ptime.span -> Span.t

Warning: Subnanosecond information is lost in this conversion

val timestamp_of_ptime : Ptime.t -> timestamp

Warning: Subnanosecond information is lost in this conversion

val day_count_of_year : year:int -> int
val day_count_of_month : year:int -> month:int -> int
val week_count_of_iso_year : year:int -> int

Month utils

type month = [
  1. | `Jan
  2. | `Feb
  3. | `Mar
  4. | `Apr
  5. | `May
  6. | `Jun
  7. | `Jul
  8. | `Aug
  9. | `Sep
  10. | `Oct
  11. | `Nov
  12. | `Dec
]
val human_int_of_month : month -> int

This yields the usual human readable numbering of 1 to 12 inclusive

val index_of_month : month -> int

This yields the index based numbering of 0 to 11 inclusive

val month_of_human_int : int -> month option
val month_of_index : int -> month option
val weekday_of_tm_int : int -> weekday option
val tm_int_of_weekday : weekday -> int
val weekday_of_iso_int : int -> weekday option
val iso_int_of_weekday : weekday -> int
val get_local_tz_for_arg : unit -> Time_zone.t
val abbr_string_of_weekday : weekday -> string

Warning: Following functions are direct applications of the relevant formulas with little to no error checking.

You are advised to read the source code of the following functions in date_time_utils.ml if you intend to use them to ensure they behave as you expect.

val is_leap_year : year:int -> bool
val jd_of_ymd : year:int -> month:int -> day:int -> int
val jd_of_ydoy : year:int -> day_of_year:int -> int
val jd_of_date : Date.t -> int
val jd_of_unix_epoch : int
val jd_span_of_unix_epoch : Span.t
val jd_of_iso_week_date : year:int -> week:int -> weekday:weekday -> int
val ymd_of_jd : int -> int * int * int
val weekday_of_jd : int -> weekday
val iso_week_date_of_jd : int -> int * int * weekday
val doy_of_ymd : year:int -> month:int -> day:int -> int
diff --git a/timedesc/Timedesc/index.html b/timedesc/Timedesc/index.html index b4738403..2b4b6697 100644 --- a/timedesc/Timedesc/index.html +++ b/timedesc/Timedesc/index.html @@ -1,5 +1,5 @@ -Timedesc (timedesc.Timedesc)

Module Timedesc

Time description and manipulations

Timedesc provides utilities to describe points of time, and properly handle calendar and time zone information.

Tutorial

Getting started

Suppose we want to get the time right now, we can simply do Timedesc.now (). But what if we want to get the time right now in a different time zone? Say New York? Then we can simply do:

Timedesc.now ~tz_of_date_time:(Timedesc.Time_zone.make_exn "America/New_York") ().

And if we want to construct a date time from scratch, we can use constructors such as make, with similar time zone specification:

Timedesc.make ~tz:(Timedesc.Time_zone.make_exn "Australia/Sydney") ~year:2021 ~month:5 ~day:30 ~hour:14 ~minute:10 ~second:0 ().

Since we deal with timestamps quite frequently, lets have a look at how Timedesc also makes working with them easier. Suppose we receive a timestamp similar to the result returned by Unix.gettimeofday, i.e. seconds since unix epoch in float, we can digest it in myriad ways. If we just want to construct a date time out of it, then we can use of_timestamp_float_s. If we want to get it into the representation used in Timedesc, say to perform arithmetic operations over it etc, then we can use Timestamp.of_float_s. But in either case, we can always swap back and forth via to_timestamp and of_timestamp.

In general it is better to use Timestamp as much as possible, unless you require a precision higher than nanosecond. This is because floating point is a lossy representation - if you convert a date time to floating point and back, you may not get the same date time back (i.e. it may not round trip). Also, performing arithmetic operations over floating points can introduce more and more errors, and it is advisable to use the arithmetic functions provided in Span or Timestamp.

To access the values of date time, we can use the constructors such as year, month, day, hour.

Time zone

By now, one nicety should be obvious: you don't have to worry about what is the time zone offset at when and where - Timedesc takes care of that for you properly! All you have to do is to make a time zone following the *nix naming convention. However, even though we follow the same naming convention, we don't actually rely on the OS time zone database, and our code will run fine on any platform.

To see what time zones Timedesc supports during run time, we can refer to Time_zone.available_time_zones. Alternatively, for a text file containing all the supported time zones by default, refer to available-time-zones.txt in the repository.

If you are aware of DST: Yes, Timedesc takes care of that for you properly as well - Timedesc does not allow you to construct a date time that does not exist for the particular time zone, and any ambiguity is made explicit as return type via local_dt_result.

This does mean Timedesc does not "resolve" the result into one of the possibilities arbitrarily, and you need to resolve the ambiguity yourself. If such a coercion is desirable, however, then you can use either min_of_local_dt_result or max_of_local_dt_result.

Span/duration

Timedesc offers both machine-friendly and human-friendly ways of dealing with spans.

For the machine-friendly side, functions in the top level of Span provide efficient constructions and arithmetic operations.

For the human-friendly side, Span.For_human provides functions which work at a level closer to human language. For instance, we say things like "2 hours and 15 minutes" quite frequently, to represent this as Span.t, we can do:

Timedesc.Span.For_human.make_exn ~hours:2 ~minutes:15 ()

And in the case of fractional descriptions, such as "1.5 hours", we can do:

Timedesc.Span.For_human.make_frac_exn ~hours:1.5 ()

Finally, to access the human friendly "view", we can use Span.For_human.view.

Using both Ptime and Timedesc

Ptime is a (very) commonly used package in projects due to being very portable, and robust. However, it lacks certain features which Timedesc provides, such as first class support for time zones, support for different date systems. As such one may wish to use both Ptime and Timedesc, especially if Ptime is already being used for a particular project.

To facilitate such use of both Ptime and Timedesc, utilities for converting to and from Ptime types are available as:

Note that Timedesc only supports nanosecond precision, while Ptime supports picosecond precision. If subnanosecond precision is a concern for you, then the above functions are not suitable.

Advanced usage

Unambiguous date time

Occasionally, we receive date times which carry both the time zone and the exact offset from UTC. Naturally we can discard the time zone since the offset alone suffices in deducing the precise timestamp. However, we can actually ask Timedesc to digest both via make_unambiguous, which checks the offset against the time zone record to make sure it is actually a possible offset.

Other calendar systems

Other than Gregorian calendar, Timedesc also supports ISO week date and ISO ordinal date.

To construct date time in the alternative systems, we can use constructors such as ISO_week_date_time.make and ISO_ord_date_time.make.

Then to access the representation in the alternative date systems, we can use accessors such as iso_week, and day_of_year.

Using date by itself

Sometimes we are only interested in the date component rather than both date and time. We can use Date module in this case.

To construct a Gregorian calendar date, we can use Date.Ymd_date.make. To construct ISO week date and ISO ordinal date, we can use Date.ISO_week_date.make and Date.ISO_ord respectively.

We have similar set of accessors for accessing values of Date.t, such as Date.year, Date.iso_week, Date.day_of_year.

To obtain a "view" (in a manner similar to the human-friendly "view" from Span.For_human), we can use Date.ISO_week_date.view and Date.ISO_ord.view.

Further reading

Misconceptions

  • Time zone offsets are always in hours
  • What we typically consider a time zone, e.g. "Europe/Paris", always has a constant offset
  • With a time zone and a specific date time, we can always obtain a unique "unix timestamp" (time since unix epoch)
  • We can always calculate time zone offset at some date time, and apply it universally for any other date time in the same time zone
  • Many more on various online resources...

Time zone, time zone offset, and date time

It is tempting to think that a time zone maps cleanly to a constant offset, and indeed we may define time zone as such, e.g. UTC+1, UTC-10, but this is far from what we mean in everyday context.

Very often, what we consider to be time zone actually represents a table which records what offset to use in which period, which we index/refer to by geographical names like "Europe/Paris", "Australia/Sydney". These tables are defined by governmental bodies, and attributes of the table, such as offset of any particular period, start and end of any particular period, may not show any observable pattern.

Thus it is not uncommon to see date time errors arising from attempts of applying some formulas universally, which might work well for a lot of cases in contemporary time periods, but fail for some combinations.

We make explicit of above explanation by considering "Europe/Paris" as an example, which observes a common form of transition called Daylight Saving Time (DST).

When DST starts (usually in March), the clocks "jump forward" by 1 hour, usually jumping from 2am to 3am, leading 2am to 3am (exclusive) to become non-existent.

Indeed we can observe the lack of continuity of Europe/Paris timeline below (UTC timeline is always continuous):

                         Mar
+Timedesc (timedesc.Timedesc)

Module Timedesc

Time description and manipulations

Timedesc provides utilities to describe points of time, and properly handle calendar and time zone information.

Tutorial

Getting started

Suppose we want to get the time right now, we can simply do Timedesc.now (). But what if we want to get the time right now in a different time zone? Say New York? Then we can simply do:

Timedesc.now ~tz_of_date_time:(Timedesc.Time_zone.make_exn "America/New_York") ().

And if we want to construct a date time from scratch, we can use constructors such as make, with similar time zone specification:

Timedesc.make ~tz:(Timedesc.Time_zone.make_exn "Australia/Sydney") ~year:2021 ~month:5 ~day:30 ~hour:14 ~minute:10 ~second:0 ().

Since we deal with timestamps quite frequently, lets have a look at how Timedesc also makes working with them easier. Suppose we receive a timestamp similar to the result returned by Unix.gettimeofday, i.e. seconds since unix epoch in float, we can digest it in myriad ways. If we just want to construct a date time out of it, then we can use of_timestamp_float_s. If we want to get it into the representation used in Timedesc, say to perform arithmetic operations over it etc, then we can use Timestamp.of_float_s. But in either case, we can always swap back and forth via to_timestamp and of_timestamp.

In general it is better to use timestamp as much as possible, unless you require a precision higher than nanosecond. This is because floating point is a lossy representation - if you convert a date time to floating point and back, you may not get the same date time back (i.e. it may not round trip). Also, performing arithmetic operations over floating points can introduce more and more errors, and it is advisable to use the arithmetic functions provided in Span or Timestamp.

To access the values of date time, we can use the constructors such as year, month, day, hour.

Time zone

By now, one nicety should be obvious: you don't have to worry about what is the time zone offset at when and where - Timedesc takes care of that for you properly! All you have to do is to make a time zone following the *nix naming convention. However, even though we follow the same naming convention, we don't actually rely on the OS time zone database, and our code will run fine on any platform.

To see what time zones Timedesc supports during run time, we can refer to Time_zone.available_time_zones. Alternatively, for a text file containing all the supported time zones by default, refer to available-time-zones.txt in the repository.

If you are aware of DST: Yes, Timedesc takes care of that for you properly as well - Timedesc does not allow you to construct a date time that does not exist for the particular time zone, and any ambiguity is made explicit as return type via local_dt_result.

This does mean Timedesc does not "resolve" the result into one of the possibilities arbitrarily, and you need to resolve the ambiguity yourself. If such a coercion is desirable, however, then you can use either min_of_local_dt_result or max_of_local_dt_result.

Span/duration

Timedesc offers both machine-friendly and human-friendly ways of dealing with spans.

For the machine-friendly side, functions in the top level of Span provide efficient constructions and arithmetic operations.

For the human-friendly side, Span.For_human provides functions which work at a level closer to human language. For instance, we say things like "2 hours and 15 minutes" quite frequently, to represent this as Span.t, we can do:

Timedesc.Span.For_human.make_exn ~hours:2 ~minutes:15 ()

And in the case of fractional descriptions, such as "1.5 hours", we can do:

Timedesc.Span.For_human.make_frac_exn ~hours:1.5 ()

Finally, to access the human friendly "view", we can use Span.For_human.view.

Using both Ptime and Timedesc

Ptime is a (very) commonly used package in projects due to being very portable, and robust. However, it lacks certain features which Timedesc provides, such as first class support for time zones, support for different date systems. As such one may wish to use both Ptime and Timedesc, especially if Ptime is already being used for a particular project.

To facilitate such use of both Ptime and Timedesc, utilities for converting to and from Ptime types are available as:

Note that Timedesc only supports nanosecond precision, while Ptime supports picosecond precision. If subnanosecond precision is a concern for you, then the above functions are not suitable.

Advanced usage

Unambiguous date time

Occasionally, we receive date times which carry both the time zone and the exact offset from UTC. Naturally we can discard the time zone since the offset alone suffices in deducing the precise timestamp. However, we can actually ask Timedesc to digest both via make_unambiguous, which checks the offset against the time zone record to make sure it is actually a possible offset.

Other calendar systems

Other than Gregorian calendar, Timedesc also supports ISO week date and ISO ordinal date.

To construct date time in the alternative systems, we can use constructors such as ISO_week_date_time.make and ISO_ord_date_time.make.

Then to access the representation in the alternative date systems, we can use accessors such as iso_week, and day_of_year.

Using date by itself

Sometimes we are only interested in the date component rather than both date and time. We can use Date module in this case.

To construct a Gregorian calendar date, we can use Date.Ymd.make. To construct ISO week date and ISO ordinal date, we can use Date.ISO_week_date.make and Date.ISO_ord.make respectively.

We have similar set of accessors for accessing values of Date.t, such as Date.year, Date.iso_week, Date.day_of_year.

To obtain a "view" (in a manner similar to the human-friendly "view" from Span.For_human), we can use Date.ISO_week_date.view and Date.ISO_ord.view.

Further reading

Misconceptions

  • Time zone offsets are always in hours
  • What we typically consider a time zone, e.g. "Europe/Paris", always has a constant offset
  • With a time zone and a specific date time, we can always obtain a unique "unix timestamp" (time since unix epoch)
  • We can always calculate time zone offset at some date time, and apply it universally for any other date time in the same time zone
  • Many more on various online resources...

Time zone, time zone offset, and date time

It is tempting to think that a time zone maps cleanly to a constant offset, and indeed we may define time zone as such, e.g. UTC+1, UTC-10, but this is far from what we mean in everyday context.

Very often, what we consider to be time zone actually represents a table which records what offset to use in which period, which we index/refer to by geographical names like "Europe/Paris", "Australia/Sydney". These tables are defined by governmental bodies, and attributes of the table, such as offset of any particular period, start and end of any particular period, may not show any observable pattern.

Thus it is not uncommon to see date time errors arising from attempts of applying some formulas universally, which might work well for a lot of cases in contemporary time periods, but fail for some combinations.

We make explicit of above explanation by considering "Europe/Paris" as an example, which observes a common form of transition called Daylight Saving Time (DST).

When DST starts (usually in March), the clocks "jump forward" by 1 hour, usually jumping from 2am to 3am, leading 2am to 3am (exclusive) to become non-existent.

Indeed we can observe the lack of continuity of Europe/Paris timeline below (UTC timeline is always continuous):

                         Mar
 UTC          -------------|-------------
                          1am
 
@@ -35,7 +35,7 @@
   minute:int ->
   second:int ->
   unit ->
-  (t, error) Stdlib.result

Constructs a date time providing only a time zone (defaults to local time zone).

A precise offset is inferred if possible.

Note that this may yield a ambiguous date time if the time zone has varying offsets, causing a local date time to appear twice, e.g. countries with DST.

See make_unambiguous for the more precise construction.

See Date.Ymd_date.make for error handling of date specification.

See Time.make for error handling of time of day specification.

val make_exn : + (t, error) Stdlib.result

Constructs a date time providing only a time zone (defaults to local time zone).

A precise offset is inferred if possible.

Note that this may yield a ambiguous date time if the time zone has varying offsets, causing a local date time to appear twice, e.g. countries with DST.

See make_unambiguous for the more precise construction.

See Date.Ymd.make for error handling of date specification.

See Time.make for error handling of time of day specification.

val make_exn : ?tz:Time_zone.t -> ?ns:int -> ?s_frac:float -> diff --git a/timere/Timere/index.html b/timere/Timere/index.html index 667458a3..5e0df490 100644 --- a/timere/Timere/index.html +++ b/timere/Timere/index.html @@ -24,14 +24,7 @@ && (hour of dt is in p.hours or p.hour_ranges) && (minute of dt is in p.minutes or p.minute_ranges) && (second of dt is in p.seconds or p.second_ranges) -&& (ns of dt is in p.ns or p.ns_ranges)

Empty pattern levels are treated as wildcard, e.g. if p.years and p.year_ranges are both empty, then (dt.year is in p.years or p.year_ranges) is true.

val iso_week_pattern : - ?years:int list -> - ?year_ranges:int range list -> - ?weeks:int list -> - ?week_ranges:int range list -> - unit -> - t

Pattern matches over ISO week date times.

A pattern p matches ISO week date time dt if

(year of dt is in p.years or p.year_ranges)
-&& (week of dt is in p.weeks or p.week_ranges)

Empty pattern levels are treated as wildcard, e.g. if p.years and p.year_ranges are both empty, then (dt.year is in p.years or p.year_ranges) is true.

val years : int list -> t

years l is a shorthand for pattern ~years:l ()

val year_ranges : int range list -> t

year_ranges l is a shorthand for pattern ~year_ranges:l ()

val iso_years : int list -> t

iso_years l is a shorthand for iso_week_pattern ~years:l ()

val iso_year_ranges : int range list -> t

iso_year_ranges l is a shorthand for iso_week_pattern ~year_ranges:l ()

val months : int list -> t

months l is a shorthand for pattern ~months:l ()

val month_ranges : int range list -> t

month_ranges l is a shorthand for pattern ~month_ranges:l ()

val iso_weeks : int list -> t

iso_weeks l is a shorthand for iso_week_pattern ~weeks:l ()

val iso_week_ranges : int range list -> t

iso_week_ranges l is a shorthand for iso_week_pattern ~week_ranges:l ()

val days : int list -> t

days l is a shorthand for pattern ~month_days:l ()

val day_ranges : int range list -> t

day_ranges l is a shorthand for pattern ~month_day_ranges:l ()

val weekdays : Timedesc.weekday list -> t

weekdays l is a shorthand for pattern ~weekdays:l ()

val weekday_ranges : Timedesc.weekday range list -> t

weekday_ranges l is a shorthand for pattern ~weekday_ranges:l ()

val hours : int list -> t

hours l is a shorthand for pattern ~hours:l ()

val hour_ranges : int range list -> t

hour_ranges l is a shorthand for pattern ~hour_ranges:l ()

val minutes : int list -> t

minutes l is a shorthand for pattern ~minutes:l ()

val minute_ranges : int range list -> t

minute_ranges l is a shorthand for pattern ~minute_ranges:l ()

val seconds : int list -> t

seconds l is a shorthand for pattern ~seconds:l ()

val second_ranges : int range list -> t

second_ranges l is a shorthand for pattern ~second_ranges:l ()

val ns : int list -> t

ns l is a shorthand for pattern ~ns:l ()

val ns_ranges : int range list -> t

ns_ranges l is a shorthand for pattern ~ns_ranges:l ()

val nth_weekday_of_month : int -> Timedesc.weekday -> t

nth_weekday_of_month n wday picks the nth weekday of all months, where 1 <= n && n <= 5

  • raises Invalid_argument

    if n is out of range

Intervals

Explicit intervals

exception Interval_is_invalid
exception Intervals_are_not_sorted
val intervals : ?skip_invalid:bool -> Timedesc.Interval.t list -> t

intervals l

skip_invalid defaults to false

val interval_seq : ?skip_invalid:bool -> Timedesc.Interval.t Stdlib.Seq.t -> t

interval_seq s

skip_invalid defaults to false

val sorted_intervals : ?skip_invalid:bool -> Timedesc.Interval.t list -> t

sorted_intervals l

skip_invalid defaults to false

val sorted_interval_seq : +&& (ns of dt is in p.ns or p.ns_ranges)

Empty pattern levels are treated as wildcard, e.g. if p.years and p.year_ranges are both empty, then (dt.year is in p.years or p.year_ranges) is true.

val years : int list -> t

years l is a shorthand for pattern ~years:l ()

val year_ranges : int range list -> t

year_ranges l is a shorthand for pattern ~year_ranges:l ()

val months : int list -> t

months l is a shorthand for pattern ~months:l ()

val month_ranges : int range list -> t

month_ranges l is a shorthand for pattern ~month_ranges:l ()

val days : int list -> t

days l is a shorthand for pattern ~month_days:l ()

val day_ranges : int range list -> t

day_ranges l is a shorthand for pattern ~month_day_ranges:l ()

val weekdays : Timedesc.weekday list -> t

weekdays l is a shorthand for pattern ~weekdays:l ()

val weekday_ranges : Timedesc.weekday range list -> t

weekday_ranges l is a shorthand for pattern ~weekday_ranges:l ()

val hours : int list -> t

hours l is a shorthand for pattern ~hours:l ()

val hour_ranges : int range list -> t

hour_ranges l is a shorthand for pattern ~hour_ranges:l ()

val minutes : int list -> t

minutes l is a shorthand for pattern ~minutes:l ()

val minute_ranges : int range list -> t

minute_ranges l is a shorthand for pattern ~minute_ranges:l ()

val seconds : int list -> t

seconds l is a shorthand for pattern ~seconds:l ()

val second_ranges : int range list -> t

second_ranges l is a shorthand for pattern ~second_ranges:l ()

val ns : int list -> t

ns l is a shorthand for pattern ~ns:l ()

val ns_ranges : int range list -> t

ns_ranges l is a shorthand for pattern ~ns_ranges:l ()

val nth_weekday_of_month : int -> Timedesc.weekday -> t

nth_weekday_of_month n wday picks the nth weekday of all months, where 1 <= n && n <= 5

  • raises Invalid_argument

    if n is out of range

Intervals

Explicit intervals

exception Interval_is_invalid
exception Intervals_are_not_sorted
val intervals : ?skip_invalid:bool -> Timedesc.Interval.t list -> t

intervals l

skip_invalid defaults to false

val interval_seq : ?skip_invalid:bool -> Timedesc.Interval.t Stdlib.Seq.t -> t

interval_seq s

skip_invalid defaults to false

val sorted_intervals : ?skip_invalid:bool -> Timedesc.Interval.t list -> t

sorted_intervals l

skip_invalid defaults to false

val sorted_interval_seq : ?skip_invalid:bool -> Timedesc.Interval.t Stdlib.Seq.t -> t

sorted_interval_seq s

skip_invalid defaults to false

Pattern matching intervals

Pattern matching intervals are designed to handle intervals where start and end points follow some pattern, but cannot be captured by pattern efficiently, e.g. you cannot represent "5:30pm to 6:11pm" via a single pattern

module Points : sig ... end
type points = Points.t
val pattern_intervals :