aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2022-03-15 11:19:58 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2022-03-28 14:17:01 +0200
commit5db7377ba2c3891420415506b00c20febb8639f9 (patch)
treeda5bd0a65cc553d6b3290db6062c98e664f613cd
parentAdd comment about why browserify. (diff)
downloadcalp-5db7377ba2c3891420415506b00c20febb8639f9.tar.gz
calp-5db7377ba2c3891420415506b00c20febb8639f9.tar.xz
Add texinfo doc for (datetime).
-rw-r--r--doc/ref/guile.texi2
-rw-r--r--doc/ref/guile/datetime.texi680
2 files changed, 682 insertions, 0 deletions
diff --git a/doc/ref/guile.texi b/doc/ref/guile.texi
index 9443e0a3..7899c9f9 100644
--- a/doc/ref/guile.texi
+++ b/doc/ref/guile.texi
@@ -1,6 +1,7 @@
@node Guile
@chapter Guile
+@include guile/datetime.texi
@include guile/util.texi
@include guile/util-path.texi
@include guile/util-config.texi
@@ -122,3 +123,4 @@ Note that @var{body} is guarded through a dynamic-wind, meaning that
even non-local exits will restore @var{component} to its initial
state.
@end defmac
+
diff --git a/doc/ref/guile/datetime.texi b/doc/ref/guile/datetime.texi
new file mode 100644
index 00000000..d49c4ada
--- /dev/null
+++ b/doc/ref/guile/datetime.texi
@@ -0,0 +1,680 @@
+@node Datetime
+@section Datetime
+
+My datetime library, with focus on date manipulation in ways sensible
+for humans. So that a date-time plus one day always keep the time of
+day.
+For example, 26 mars 2022 10:00 plus 1 day would give 27 mars 2022
+10:00, even though 25 hours have passed due to summer time starting
+(in Sweden).
+
+Note that while some of these procedures mentions timezones, almost
+nothing is actually done with it.
+
+@subsection Constants
+
+@defvar jan
+@defvarx january
+@defvarx feb
+@defvarx february
+@defvarx mar
+@defvarx mars
+@defvarx apr
+@defvarx april
+@defvarx may
+@defvarx jun
+@defvarx june
+@defvarx jul
+@defvarx july
+@defvarx aug
+@defvarx august
+@defvarx sep
+@defvarx september
+@defvarx oct
+@defvarx october
+@defvarx nov
+@defvarx november
+@defvarx dec
+@defvarx december
+Numeric constants for all months.
+@code{@var{jan} = 1}, @code{@var{dec} = 12}.
+@end defvar
+
+@defvar sun
+@defvarx sunday
+@defvarx mon
+@defvarx monday
+@defvarx tue
+@defvarx tuesday
+@defvarx wed
+@defvarx wednesday
+@defvarx thu
+@defvarx thursday
+@defvarx fri
+@defvarx friday
+@defvarx sat
+@defvarx saturday
+@anchor{sunday}
+Numeric constants for all weekdays.
+@code{@var{sunday} = 0}, @code{@var{saturday} = 6}.
+@end defvar
+
+@subsection Parameters and Configuration
+
+@deftp {parameter} week-start
+@anchor{week-start}
+Which weekday should be considered the first. Used for calculating
+week numbers, the start dates of week, and is available for UI-code
+and the like which wants it.
+@end deftp
+
+@deftp {config} week-start
+Configuration item, updates @xref{week-start}.
+@end deftp
+
+
+@subsection Datatypes
+
+@deftp {Immutable Record} <date> year month day
+Object representing a date, without any timezone information.
+Given the date 2040-03-23 (in ISO-8601 format), @var{year} = 2020,
+@var{month} = 3 and @var{day} = 23.
+
+Values higher than those usually used are possible, but not recommended.
+
+@defun date? x
+Is @var{x} a date object?
+@end defun
+
+@defun date [#:year=0] [#:month=0] [#:day=0]
+Create a new date object.
+@end defun
+
+@defun year <date>
+@defunx month <date>
+@defunx day <date>
+Fetch corresponding field from the date object.
+@end defun
+@end deftp
+
+@deftp {Immutable Record} <time> hour minute second
+Object representing a timestamp in a given day,
+without any timezone information.
+Given the time 10:20:30, @var{hour} = 10,
+@var{minute} = 20 and @var{second} = 30.
+
+Values larger than the ``regular'' are allowed, and useful since this
+type is also used for time offsets.
+
+@defun time? x
+Is @var{x} a time object?
+@end defun
+
+@defun time [#:hour=0] [#:minute=0] [#:second=0]
+Create a new time object.
+@end defun
+
+@defun hour <time>
+@defunx minute <time>
+@defunx second <time>
+Fetch corresponding field from the time object.
+@end defun
+@end deftp
+
+
+@deftp {Immutable Record} <datetime> date time tz
+
+A collation of date and time, along with an optional timezone.
+Set @code{tz = #f} if a timezone is not desired.
+
+@defun datetime? x
+Is @var{x} a datetime object?
+@end defun
+
+@defun datetime [#:date] [#:time] [#:tz] [#:year=0] [#:month=0] [#:day=0] [#:hour=0] [#:minute=0] [#:second=0]
+Creates a new <datetime>. If @var{date} or @var{time} is given, those
+are used. Otherwise, a date object is created from @var{year},
+@var{month} and @var{day}, and time is respectively created from
+@var{hour}, @var{minute} and @var{second}.
+@end defun
+
+@defun get-date
+@defunx get-timezone
+Note that @code{get-time} doesn't exists.
+@end defun
+@end deftp
+
+
+@subsection Reader Extensions
+
+This module registers reader extensions on @code{#0}, @code{#1}, and
+@code{#2}. These read either dates, times, or datetimes; using @code{string->date/-time}.
+
+@c @subsection CTIME
+
+@c These procedures are for interfacing with C's time procedures, see CTIME(3).
+
+@c The datetime<->tm procedures are internal, since they are slightly
+@c unstable (see comments in code).
+@c They are thereby not documented.
+@c @defun datetime->tm datetime
+@c Convert a @code{<datetime>} object to a @code{struct tm}, encoded in a
+@c scheme vector.
+@c @end defun
+@c
+@c @defun tm->datetime tm
+@c Converts a @code{struct tm}, as returned from @code{datetime->tm} back
+@c into a @code{<datetime>} object.
+@c @end defun
+
+@subsection Procedures
+
+@defun datetime->unix-time datetime
+Converts @var{datetime} to an integer representing its unix time.
+@end defun
+
+@defun unix-time->datetime n
+Converts a given unix timestamp to a datetime object.
+Currently forces the timezone to be UTC.
+@end defun
+
+@defun current-datetime
+Return a datetime object of the current date and time.
+Currently always returns it in UTC.
+@end defun
+
+@defun current-date
+Get the date component from a call to @code{current-datetime}.
+@end defun
+
+
+@defun get-datetime datetime
+Takes a datetime in any timezone, and renormalize it to local time (as
+defined by the environment variable TZ). This means that given UTC
+10:00 new years day would return 11:00 new years day if ran in sweden.
+@end defun
+
+
+@defun as-date date/-time
+@defunx as-time date/-time
+Both procedures takes a <date>, <time>, or <datetime>, and return
+respectively a <date> or <time> object.
+
+@code{as-date}, when given a time will return a zeroed date object.
+Vice versa for @code{as-time}.
+@end defun
+
+@defun as-datetime date/-time
+Takes a <date>, <time>, or <datetime>, and returns a <datetime> object
+with the same data, with the (possibly) missing date or time set to
+all zeroes.
+@end defun
+
+
+@defun date-zero? date
+@defunx time-zero? time
+Checks if all components are zero.
+@end defun
+
+
+@defun leap-year? year
+Given an integer @var{year}, return @code{#t} if it's a leap year, and
+@code{#f} otherwise.
+@end defun
+
+@defun days-in-month date
+Returns how many days are in the month specified by the <date> @var{date}.
+Note that the day component is ignored.
+@end defun
+
+@defun days-in-year date
+Returns how many days are in the year pointed to by @var{date}.
+@end defun
+
+@defun start-of-month date
+Returns a <date> object equal to date, but with the day component set
+to 1.
+@end defun
+
+@defun end-of-month date
+Returns a <date> object equal to date, but with the day component set
+to the last day of the month.
+
+@example
+(end-of-month #2020-01-10)
+⇒ #2020-01-31
+(end-of-month #2020-02-01)
+⇒ #2020-02-29
+@end example
+@end defun
+
+
+@defun start-of-year date
+Returns a <date> object equal to date, but with the day and month
+component set to 1.
+@end defun
+
+@defun date-stream date-increment start-day
+Returns an @ref{(guile)SRFI-43} stream of <date> objects, starting at
+@var{start-day} and stepping in increments of @var{date-increment}.
+@end defun
+
+@defun day-stream start-day
+Returns a stream of each day from @var{start-day}.
+@end defun
+
+@defun month-stream start-day
+Returns a stream of each months from @var{start-day}.
+Day component stays the same.
+@end defun
+
+@defun week-stream start-day
+Returns a stream of each week from @var{start-day}
+(increments of 7 days).
+@end defun
+
+@defun time-min a b
+@defunx time-max a b
+@defunx date-min a b
+@defunx date-max a b
+@defunx datetime-min a b
+@defunx datetime-max a b
+Returns the smaller (or larger) of @var{a} or @var{b}.
+@end defun
+
+@defun month+ date [change=1]
+@defunx month- date [change=1]
+Equivalent to @code{(date+ date (date month: change))}.
+@end defun
+
+@defun week-day date
+Returns an integer representing the week day of @var{date}.
+@ref{sunday}
+@end defun
+
+
+@defun week-1-start date [week-start=(week-start)]
+Returns the date which week 1 starts on, according to the (at least)
+Swedish rule of week counting.
+@ref{week-start}
+@end defun
+
+
+@defun week-number date [week-start=(week-start)]
+Returns the week number of @var{date}, according to the (at least)
+Swedish rule of week counting.
+@ref{week-start}
+@end defun
+
+@defun date-starting-week week-number date [week-start=(week-start)]
+Returns the first day of week @var{week-number}, @var{date} is used
+for year information.
+@ref{week-start}
+@end defun
+
+
+@defun week-day-name week-day [truncate-to] [#:key locale]
+Returns the locale dependent name for the given week day.
+
+@var{week-day} is a number per @ref{sunday}.
+@var{truncate-to} may be a number, which limits to the first @var{n}
+letters of the resulting string.
+@end defun
+
+
+@defun timespan-overlaps? s1-begin s1-end s2-begin s2-end
+Check if the interval @var{s1-begin} to @var{s1-end} overlaps with the
+interval @var{s2-begin} to @var{s2-end}.
+@end defun
+
+@defun find-first-week-day week-day date
+Returns the first instance of the given week-day after @var{date}.
+
+@example
+(find-first-week-day mon #2020-04-01)
+⇒ #2020-04-06
+(find-first-week-day mon #2020-04-10)
+⇒ #2020-04-13
+(find-first-week-day mon #2020-04-30)
+⇒ #2020-05-04
+@end example
+@end defun
+
+@defun all-wday-in-month week-day month-date
+Returns instances of the given week-day in month between
+month-date and end of month.
+@example
+(all-wday-in-month mon #2020-06-01)
+⇒ (#2020-06-01 #2020-06-08 #2020-06-15 #2020-06-22 #2020-06-29)
+(all-wday-in-month mon #2020-06-10)
+⇒ (#2020-06-15 #2020-06-22 #2020-06-29)
+@end example
+@end defun
+
+@defun all-wday-in-year week-day year-date
+Returns a list of all instances of @var{week-day} in @var{year-date}.
+@end defun
+
+@defun add-day date
+@defunx remove-day date
+@code{@var{date} ± (date day: 1)}
+@end defun
+
+@defun in-date-range? start-date end-date → date → boolean
+Returns a predicate procedure, which checks if a given date is between
+@var{start-date} and @var{end-date}.
+@end defun
+
+@defun weekday-list [week-start=(week-start)]
+Returns a list of the seven week days, with @var{week-start}
+as the beginning of the week.
+@end defun
+
+
+@defun start-of-week d [week-start=(week-start)]
+@defunx end-of-week d [week-start=(week-start)]
+Returns the date the week containing @var{d} started or ended.
+@end defun
+
+
+@defun month-days date [week-start=(week-start)]
+Given a month and and which day the week starts on,
+returns three lists, which are:
+The days leading up to the current month, but share a week
+The days in the current month
+The days after the current month, but which shares a week.
+
+@example
+ mars 2020
+må ti on to fr lö sö
+ 1
+ 2 3 4 5 6 7 8
+ 9 10 11 12 13 14 15
+16 17 18 19 20 21 22
+23 24 25 26 27 28 29
+30 31
+@end example
+@lisp
+(month-days #2020-03-01 mon)
+; ⇒ (2020-02-24 ... 2020-02-29)
+; ⇒ (2020-03-01 ... 2020-03-31)
+; ⇒ (2020-04-01 ... 2020-04-05)
+@end lisp
+Ignores day component of @var{date}.
+@end defun
+
+
+@defun days-in-interval start-date end-date
+The amount of days in the given interval, including both endpoints.
+@end defun
+
+
+@defun year-day date
+Day from start of the year, so 1 feb would be day 32.
+Also known as Julian day.
+@end defun
+
+
+@defun time->decimal-hour time
+Convert @var{time} to a decimal value, so 10:30 would become 10.5.
+@end defun
+
+@defun datetime->decimal-hour dt [start-date]
+Similar to @code{time->decimal-hour}, but also looks at the date component.
+
+@var{start-date} is required if either the month of year component of
+@var{dt} is non-zero (since months and years have a variable number of hours).
+@end defun
+
+@defun date-range start end [increment=(date day: 1)]
+Returns a list of all dates from start to end.
+Both inclusive
+@end defun
+
+@defun locale-month
+@defunx locale-month-short
+These are direct re-exports from (ice-9 i18n)
+
+@xref{Accessing Locale Information,,,guile}.
+@end defun
+
+@defun date= args ...
+@defunx date=? args ...
+@defunx date< args ...
+@defunx date<? args ...
+@defunx date> args ...
+@defunx date>? args ...
+@defunx date<= args ...
+@defunx date<=? args ...
+@defunx date>= args ...
+@defunx date>=? args ...
+Checks if all date arguments satisfy the predicate.
+@end defun
+
+@defun time= args ...
+@defunx time=? args ...
+@defunx time< a b
+@defunx time<? a b
+@defunx time> a b
+@defunx time>? a b
+@defunx time<= a b
+@defunx time<=? a b
+@defunx time>= a b
+@defunx time>=? a b
+Checks if all time arguments satisfy the predicate.
+@end defun
+
+@defun datetime= args ...
+@defunx datetime=? args ...
+@defunx datetime< a b
+@defunx datetime<? a b
+@defunx datetime> a b
+@defunx datetime>? a b
+@defunx datetime<= a b
+@defunx datetime<=? a b
+@defunx datetime>= a b
+@defunx datetime>=? a b
+Check if all datetime arguments satisfy the predicate.
+The timezone field is ignored.
+@end defun
+
+@defun date/-time< a b
+@defunx date/-time<? a b
+@defunx date/-time> a b
+@defunx date/-time>? a b
+@defunx date/-time<= a b
+@defunx date/-time<=? a b
+@defunx date/-time>= a b
+@defunx date/-time>=? a b
+Equivalent to the @code{datetime*} versions, but wraps its arguments
+in @code{as-datetime}.
+@end defun
+
+@subsection Arithmetic
+
+While only one date (and one time) type is available, it really should
+be seen as two. Absolute dates, such as the fourth of november,
+2022. The other type are intervals, such as 3 years, 4 months and 2 days.
+
+A ``type mismatch'' might therefore lead to some confounding results.
+@example
+(date- #2020-01-01 #2020-01-01)
+⇒ #00-1-11-31
+(date-difference #2020-01-01 #2020-01-01)
+⇒ #0000-00-00
+@end example
+
+@defun date+ base rest ...
+@defunx date- base rest ...
+Add or remove each difference from base.
+@end defun
+
+@defun date-difference end start
+Returns difference between the two dates, in years, months, and days.
+In such a way that
+
+@lisp
+(date= (date+ start (date-difference end start)))
+@end lisp
+@end defun
+
+@defun time+ base rest ...
+@defunx time- base rest ...
+Adds (or subtracts) each difference from the base, and returns two
+values. The sum, and how many midnight's have passed.
+
+@lisp
+(time+ #22:00:00 (time hour: 4))
+⇒ #02:00:00
+⇒ 1
+@end lisp
+@end defun
+
+@defun datetime+ base change
+@defunx datetime- base change
+@end defun
+
+@defun datetime-difference end start
+@end defun
+
+@subsection Parsing and Formatting
+
+@defun datetime->string datetime [fmt=''~Y-~m-~dT~H:~M:~S''] [#:allow-unknown?]
+
+Formats @var{datetime} into a string.
+The function will throw an error when encountering an unknown format
+specifier, unless @var{#:allow-unknown} is true.
+
+@table @samp
+@item ~~
+A literal tilde (~).
+@item ~H
+Hour, left padded with zeroes to length 2.
+@item ~k
+Like @samp{~H}, but padded with spaces.
+@item ~M
+Minute, left padded with zeroes to length 2.
+@item ~S
+Seconds, left padded with zeroes to length 2.
+@item ~Y
+Year, left padded with zeroes to length 4;
+@item ~m
+Month number, left padded with zeroes to length 2.
+@item ~d
+Day in month, left padded with zeroes to length 2.
+@item ~s
+Epoch time, per UNIX.
+@item ~e
+Same as @samp{~d}, but padded with spaces.
+@item ~1
+Shorthand for @samp{~Y-~m-~d}.
+@item ~3
+Shorthand for @samp{~H:~M:~S}.
+@item ~A
+Locale week day name.
+@item ~a
+Locale week day name, truncated to 3 characters.
+@item ~b
+Locale month name, truncated.
+@item ~B
+Locale month name, in full.
+@item ~Z
+@samp{Z} if the timezone is @samp{UTC}. Nothing otherwise.
+@end table
+@end defun
+
+@defun date->string date [fmt=''~Y-~m-~d''] [#:allow-unknown?]
+@defunx time->string date [fmt=''~H:~M:~S''] [#:allow-unknown?]
+Simple wrappers around @code{datetime->string}, which works directly
+on date or time objects.
+@end defun
+
+
+@defun string->datetime str [fmt=''~Y-~m-~dT~H:~M:~S~Z''] [locale=%global-locale]
+Attempts to parse @var{str} as a datetime, according to the ruleset @var{fmt}.
+An invalid or unparsable string will throw an error.
+
+Each token in @var{fmt} informs the parser what the next expected
+token in @var{str} is. If a binding rule is parsed multiple times,
+then the last one is used for the resulting object. For example,
+@example
+(string->datetime "10:20" "~H:~H")
+⇒ (datetime hour: 20)
+@end example
+
+spaces are literal, there is no way to match an arbitrary number of
+whitespace characters
+
+@table @samp
+@item ~~
+Next token is a literal tilde.
+
+@item ~Z
+If next token is a literal @samp{Z} then the resulting timezone is set
+to @samp{UTC}, otherwise does nothing.
+
+@item ~p
+The next token is an AM/PM indicator, matched by the regex
+@code{^([AaPp])[.]?[Mm][.]?}. A valid token will reinterpret the last
+hour indicator as 12-hour time (instead of 24 hour time), regardless
+if its before or after this token.
+
+@item ~b
+@itemx ~B
+@itemx ~h
+Parses a month by name, just as @code{parse-month}.
+
+@item ~H
+@itemx ~M
+@itemx ~S
+@itemx ~m
+@itemx ~d
+Parses up to two digits, but possibly less if a non-digit appears in
+the string. Then stores the resulting value in either the hour,
+minute, second, month, or day slot of the resulting object.
+
+This double function allows both dates without delimiters, such as
+``0102'' to be correctly parsed, but also more free form formats, such
+as ``1 jan''.
+
+@item ~Y
+Equivalent to @samp{~H}, but reads up to 4 digits, and stores the
+result in the year field.
+@end table
+@end defun
+
+
+@defun parse-month str [locale=%global-locale]
+Returns the first month whose name has @var{str} as its prefix.
+The result will be on the interval [1, 12], or -1 if no month matched.
+@end defun
+
+
+@defun string->time str [fmt=''~H:~M:~S''] [locale=%global-locale]
+@defunx string->date str [fmt=''~Y-~m-~d''] [locale=%global-locale]
+Wrappers around @code{string->datetime}, but only returning the time
+or date component.
+@end defun
+
+
+@defun string->date/-time string
+Parses string as an ISO-8601 string. Checks for the existence of
+@code{T}, @code{:}, or @code{-} to determine if it's a datetime, time
+or date.
+@end defun
+
+@defun parse-ics-date str
+@defunx parse-ics-time str
+@defunx parse-ics-datetime str [zone]
+Parses dates per RFC5545.
+@end defun
+
+@defun parse-iso-date str
+@defunx parse-iso-time str
+@defunx parse-iso-datetime str
+Parses (the well known subset) of ISO-compatible dates.
+@end defun
+
+@defun parse-freeform-date str
+Currently an alias for parse-iso-datetime, but should preferably be extended.
+@end defun