Date! datatype

1. Abstract

Date! values represent calendar dates, relying on the Gregorian calendar. A date value can also contain optional time and timezone information. Time in dates is expressed in 24-hour format (including optional time zone information). Red’s dates also have an extensive support for ISO 8601 input formats.

Note:

  • date! uses a proleptic Gregorian calendar, extending its usage backward, beyond the year 1582. Care should be taken when trying to represent historical, pre-Gregorian dates using date! values.

  • Supported dates range from 1/Jan/-16384 to 31/Dec/16383, wrapping around on overflowing math operations. On input, that range is reduced from 1/Jan/-9999 to 31/Dec/9999 for practical reasons.

2. Creation

Date! values can be created using literal syntax, or at runtime using a make constructor or a to conversion.

2.1. Literal syntax

Many different literal formats are supported, including all Rebol date formats and most of the ISO date standard.

<date>/<time>
<date>/<time><zone>
<date>T<time>
<date>T<time>Z
<date>T<time><zone>

<date> formats:
    <yyyy><sep><mmm><sep><dd>
    <dd><sep><mmm><sep><yyyy>
    <dd><sep><mmm><sep><yy>

Additional <date> formats when followed by T:
    <yyyy><mm><dd>
    <yyyy>-W<ww>
    <yyyy>-W<ww>-<d>
    <yyyy>-<ddd>

<mmm> formats (month):
    <m>
    <mon>
    <month>

<time> formats:
    <hour>:<min>:<sec>
    <hour>:<min>:<sec><zone>
    <hhmmss>
    <hhmmss><zone>
    <hhmmss>.<dec>
    <hhmmss>.<dec><zone>
    <hhmm>
    <hhmm><zone>

<zone> formats (timezone):
    <sign><hour>
    <sign><hour>:<min15>
    <sign><hhmm>

<sec> formats (seconds):
    <ss>
    <ss>.<dec>

<sep>    : `-` or `/`
<yyyy>   : 3 or 4 digits representing the year (4 digits for ISO dates)
<yy>     : 2 digits representing the year relative to 2000
<m>      : 1 or 2 digits representing the month
<mm>     : 2 digits representing the month
<mon>	 : 3 letters representing the beginning of the month
<month>  : full name of the month
<d>      : a digit representing the day of the week (1 to 7)
<dd>     : 1 or 2 digits representing the day of the month
<ddd>    : 3 digits representing the day of the year
<ww>     : 2 digits representing the week of the year
<time>   : time! value
<hour>   : 1 or 2 digits representing the hours
<min>    : 1 or 2 digits representing the minutes
<ss>     : 1 or 2 digits representing the seconds
<dec>    : decimals for seconds
<sign>   : `+` or `-` character (cannot be omitted)
<min15>  : same as <min> but rounded to a multiple of 15.
<hhmm>   : 4 digits for hours and minutes (no separator)
<hhmmss> : 6 digits for hours, minutes and seconds (no separator)

Many different input formats for literal dates are accepted. Out of range values (exceeding the specified digit numbers or beyond a field’s norm) will result in a syntax error. When serialized again (e.g. for displaying), only the following canonical formats are used:

<dd>-<mon>-<yyyy>
<dd>-<mon>-<yyyy>/<hour>:<min>:<sec>
<dd>-<mon>-<yyyy>/<hour>:<min>:<sec><sign><hour>:<min15>

When the time and/or zone fields are unset, they are omitted. For negative dates, the / separator is used instead of - for better readability.

Notes:

  • When a month is specified using letters, the month is expressed using its English name, and is case-insensitive.

  • When a year is specified using only 2 digits (yy): if it is < 50, it’s interpreted as 20yy, otherwise, it’s interpreted as 19yy.

Examples of valid input dates:

1999-10-5
1999/10/5
5-10-1999
5/10/1999
5-October-1999
1999-9-11
11-9-1999
5/sep/2012
5-SEPTEMBER-2012

02/03/04
02/03/71

5/9/2012/6:0
5/9/2012/6:00
5/9/2012/6:00+8
5/9/2012/6:0+0430
4/Apr/2000/6:00+8:00
1999-10-2/2:00-4:30
1/1/1990/12:20:25-6

2017-07-07T08:22:23+00:00
2017-07-07T08:22:23Z
20170707T082223Z
20170707T0822Z
20170707T082223+0530

2017-W01
2017-W23-5
2017-W23-5T10:50Z
2017-001
2017-153T10:50:00-4:00

2.2. Runtime creation

make date! [<day> <month> <year>]
make date! [<year> <month> <day>]
make date! [<day> <month> <year> <time>]
make date! [<day> <month> <year> <time> <zone>]
make date! [<day> <month> <year> <hour> <minute> <second>]
make date! [<day> <month> <year> <hour> <minute> <second> <zone>]

<year>   : integer! value
<month>  : integer! value
<day>    : integer! value
<time>   : time! value
<zone>   : integer!, time! or pair! value
<hour>   : integer! value
<minute> : integer! value
<second> : integer! value

Notes:

  • Out of range argument values will result in an error. For a normalized result, use the to action instead of make.

  • year and day fields are interchangeable, but only for low year values. The year can be used in first position only if its value is >= 100 and less than the value of the third field. When that rule is not satisfied, the third field is considered the year. Negative years should always be specified in the third position.

Examples

make date! [1978 2 3]
== 3-Feb-1978

make date! [1978 2 3 5:0:0 8]
== 3-Feb-1978/5:00:00+08:00

make date! [1978 2 3 5:0:0]
== 3-Feb-1978/5:00:00

make date! [1978 2 3 5 20 30]
== 3-Feb-1978/5:20:30

make date! [1978 2 3 5 20 30 -4]
== 3-Feb-1978/5:20:30-4:00


make date! [100 12 31]
== 31-Dec-0100

; 32 isn't a valid day
make date! [100 12 32]
*** Script Error: cannot MAKE/TO date! from: [100 12 32]
*** Where: make

; First field is < 100, so not considered as a year
make date! [99 12 31]
*** Script Error: cannot MAKE/TO date! from: [99 12 31]
*** Where: make

3. Path accessors

Path accessors provide a convenient way for getting and setting all date! value fields.

3.1. /date

Syntax

<date>/date
<date>/date: <date2>

<date>  : a word or path expression referring to a date! value
<date2> : a date! value

Description

Gets or sets the date field of a date (excluding time and zone). Dates are returned as date! values.

Examples

d:  now
== 10-Jul-2017/22:46:22-06:00
d/date
== 10-Jul-2017

d/date: 15/09/2017
== 15-Sep-2017/22:46:22-06:00

3.2. /year

Syntax

<date>/year
<date>/year: <year>

<date> : a word or path expression referring to a date! value
<year> : an integer! value

Description

Gets or sets the year field of a date. Years are returned as integers. Out of range argument values will result in a normalized date.

Examples

d:  now
== 10-Jul-2017/22:46:22-06:00
d/year: 16383
== 16383
d
== 10-Jul-16383/22:46:22-06:00
d/year: 16384
== 16384
d
== 10/Jul/-16384/22:46:22-06:00     ; note wrap on overflow past year 16384
d/year: 32767
== 32767
d
== 10/Jul/-1/22:46:22-06:00
d/year: 32768
== 32768
d
== 10-Jul-0000/22:46:22-06:00

3.3. /month

Syntax

<date>/month
<date>/month: <month>

<date>  : a word or path expression referring to a date! value
<month> : an integer! value

Description

Gets or sets the month field of a date. Months are returned as integers. Out of range argument values will result in a normalized date.

Examples

d: now
== 10-Jul-2017/22:48:31-06:00
d/month: 12
== 12
d
== 10-Dec-2017/22:48:31-06:00
d/month: 13
== 13
d
== 10-Jan-2018/22:48:31-06:00   ; Note wrap to the next year
d/month
== 1                            ; Month is now normalized

3.4. /day

Syntax

<date>/day
<date>/day: <day>

<date> : a word or path expression referring to a date! value
<day>  : an integer! value

Description

Gets or sets the day field of a date. Days are returned as integers. Out of range argument values will result in a normalized date.

Examples

 d: 1-jan-2017
== 1-Jan-2017
d/day: 32
== 32
d
== 1-Feb-2017
d/day: 0         ; Note how zero works, for proper date math
== 0
d
== 31-Jan-2017

3.5. /time

Syntax

<date>/time
<date>/time: <time>

<date> : a word or path expression referring to a date! value
<time> : a time! or none! value

Description

Gets or sets the time field of a date. Times are returned as time! values, or none! value if time is not set, or has been reset (see below). Out of range argument values will result in a normalized date.

If the time is set to a none! value, the time and zone fields are set to zero and will not be shown further.

Examples

d: now
== 10-Jul-2017/23:18:54-06:00
d/time: 1:2:3
== 1:02:03
d
== 10-Jul-2017/1:02:03-06:00
d/time: none
== 10-Jul-2017

3.6. /hour

Syntax

<date>/hour
<date>/hour: <hour>

<date> : a word or path expression referring to a date! value
<hour> : an integer! value

Description

Gets or sets the time field of a date. Hours are returned as integer values between 0 and 23. Out of range argument values will result in a normalized date.

Examples

d: now
== 10-Jul-2017/23:19:40-06:00
d/hour: 0
== 0
d
== 10-Jul-2017/0:19:40-06:00
d/hour: 24
== 24
d
== 11-Jul-2017/0:19:40-06:00

3.7. /minute

Syntax

<date>/minute
<date>/minute: <minute>

<date>   : a word or path expression referring to a date! value
<minute> : an integer! value

Description

Gets or sets the minute field of a date. Minutes are returned as integer values between 0 and 59. Out of range argument values will result in a normalized date.

Examples

== 10-Jul-2017/23:20:25-06:00
d/minute: 0
== 0
d
== 10-Jul-2017/23:00:25-06:00
d/minute: 60
== 60
d
== 11-Jul-2017/0:00:25-06:00

3.8. /second

Syntax

<date>/second
<date>/second: <second>

<date>   : a word or path expression referring to a date! value
<second> : an integer! or float! value

Description

Gets or sets the second field of a date. Seconds are returned as integer! or float! values between 0 and 59. Out of range argument values will result in a normalized date.

Examples

d: now
== 10-Jul-2017/23:21:15-06:00
d/second: 0
== 0
d
== 10-Jul-2017/23:21:00-06:00
d/second: -1
== -1
d
== 10-Jul-2017/23:20:59-06:00
d/second: 60
== 60
d
== 10-Jul-2017/23:21:00-06:00

3.9. /zone

Syntax

<date>/zone
<date>/zone: <zone>

<date> : a word or path expression referring to a date! value
<zone> : a time! or integer! value

Description

Gets or sets the timezone field of a date. Timezones are returned as time! values between -16:00 and +15:00. Setting the timezone with /zone will only modify that field, time is kept the same. Out of range argument values will result in a normalized date.

When the timezone is set to an integer! argument, the argument represents hours, while minutes are set to 0.

The granularity for timezone’s minutes is 15, non-conforming values will be rounded to closest 15 minutes inferior multiple.

Examples

d: 1/3/2017/5:30:0
d/zone: 8
== 1-Mar-2017/5:30:00+08:00

d/zone: -4:00
== 1-Mar-2017/5:30:00-04:00

3.10. /timezone

Syntax

<date>/timezone
<date>/timezone: <zone>

<date>     : a word or path expression referring to a date! value
<timezone> : an integer!, time! or pair! value

Description

Gets or sets the timezone field of a date. Timezones are returned as time! values between -16:00 and +15:00. Setting the timezone with /timezone will modify both the time and the zone, keeping the new time equivalent to the old one in the new zone. Out of range argument values will result in a normalized date.

When the timezone is set to an integer! argument, the argument represents hours, while minutes are set to 0.

The granularity for timezone’s minutes is 15, non-conforming values will be rounded to closest 15 minutes inferior multiple.

Examples

d: 1/3/2017/5:30:0
d/timezone: 8
== 1-Mar-2017/13:30:00+08:00

d/timezone: -4:00
== 1-Mar-2017/1:30:00-04:00

Note:

  • Setting the /timezone to 0 will set the time to UTC.

3.11. /yearday

Syntax

<date>/yearday
<date>/yearday: <day>

<date>    : a word or path expression referring to a date! value
<yearday> : an integer! value

Description

Gets the day of the year of a date, starting at 1 for January 1st. Days are returned as integers. When used for setting the day of the year, the date is recalculated to match that day. Out of range argument values will result in a normalized date.

Note:

  • a /julian alias for /yearday is also available, for compatibility with Rebol.

Examples

d: 1-jan-2017
== 1-Jan-2017
d/yearday
== 1
d: 31-dec-2017
== 31-Dec-2017
d/yearday
== 365
d: 31-dec-2020
== 31-Dec-2020
d/yearday
== 366                  ; Leap year

d: 31-dec-2017
== 31-Dec-2017
d/yearday: 366
== 366
d
== 1-Jan-2018

3.12. /weekday

Syntax

<date>/weekday
<date>/weekday: <day>

<date>    : a word or path expression referring to a date! value
<weekday> : an integer! value

Description

Gets the week day number, ranging from 1 for Monday, to 7 for Sunday. When used for setting the day of the week, the date is recalculated to match that day in the current week. Out of range argument values will result in a normalized date.

Examples

d: now
== 10-Jul-2017/23:25:35-06:00
d/weekday
== 1
d/weekday: 2
== 2
d
== 11-Jul-2017/23:25:35-06:00
d/weekday: 7
== 7
d
== 16-Jul-2017/23:25:35-06:00
d/weekday: 8
== 8
d
== 17-Jul-2017/23:25:35-06:00

3.13. /week

Syntax

<date>/week
<date>/week: <day>

<date> : a word or path expression referring to a date! value
<week> : an integer! value

Description

Gets the week number using a casual week definition (week starts on Sunday, first week starts on January 1st), ranging from 1 for first week of the year, to 53. When used for setting the week number, the date is recalculated to match the first day of that week (a Sunday). Out of range argument values will result in a normalized date.

Note:

  • The casual week definition allows first and last weeks of the year to be partial weeks, ranging from 1 day to 7 days. For accurate week calculations across years, use the /isoweek accessor.

Examples

d: now
== 10-Jul-2017/23:28:07-06:00
d/week
== 28
d/week: 29
== 29
d
== 16-Jul-2017/23:28:07-06:00
d/week: 52
== 52
d
== 24-Dec-2017/23:28:07-06:00
d/week: 53
== 53
d
== 31-Dec-2017/23:28:07-06:00
d/week: 54
== 54
d
== 7-Jan-2018/23:28:07-06:00

3.14. /isoweek

Syntax

<date>/isoweek
<date>/isoweek: <day>

<date>    : a word or path expression referring to a date! value
<isoweek> : an integer! value

Description

Gets the week number using the ISO 8601 week definition, ranging from 1 for first week of the year, to 52 (or 53 for some years). When used for setting the week number, the date is recalculated to match the first day of that week (a Monday). Out of range argument values will result in a normalized date.

Examples

d: now
== 10-Jul-2017/23:29:13-06:00
d/isoweek
== 28
d/isoweek: 29
== 29
d
== 17-Jul-2017/23:29:13-06:00
d/isoweek: 52
== 52
d
== 25-Dec-2017/23:29:13-06:00
d/isoweek: 53
== 53
d
== 1-Jan-2018/23:29:13-06:00

3.15. Ordinal accessors

In addition to using words for accessing the date fields, it is also possible to use an integer index in path expression:

<date>/<index>

<date>  : a word or path expression referring to a date! value
<index> : an integer! value referring to a date field.

Such ordinal accessor can be used both for getting or setting fields. The following table gives the equivalent field names

Index Name

1

date

2

year

3

month

4

day

5

zone

6

time

7

hour

8

minute

9

second

10

weekday

11

yearday

12

timezone

13

week

14

isoweek

3.16. Accessing date fields using Pick

It is possible to access date fields without using a path, which can be more convenient in some cases. pick can be used for that on dates.

Syntax

pick <date> <field>

<date>  : a date! value
<field> : an integer! value

An integer argument represents the ordinal accessor for dates. See "Ordinal accessors" table above.

Examples

d: now
== 10-Jul-2017/23:35:01-06:00
names: system/catalog/accessors/date!
repeat i 14 [print [pad i 4 pad names/:i 10 pick d i]]
1    date       11-Jul-2017
2    year       2017
3    month      7
4    day        11
5    zone       8:00:00
6    time       21:43:52
7    hour       21
8    minute     43
9    second     52.0
10   weekday    2
11   yearday    192
12   timezone   8:00:00
13   week       28
14   isoweek    28

4. Conversions

4.1. Epoch time

Dates can be converted from/to Unix epoch time using to action.

Syntax

to-integer <date>
to-date <epoch>

<date>  : a date! value
<epoch> : an integer value representing an epoch time

Epoch time are expressed in UTC. If the argument date is not in UTC, it will be converted internally before converting to epoch time.

d: 8-Jul-2017/17:49:27+08:00
to-integer d
== 1499507367

to-integer 8-Jul-2017/9:49:27
== 1499507367

to-date to-integer d
== 8-Jul-2017/9:49:27

Note that epoch time is not defined beyond the year 2038.

4.2. Block to date

Syntax

to date! <spec>

<spec> : a block of values for date fields

The argument block will be converted to a date! value according to the same syntax as for make (see 2.2 [runtime-creation]). Out of range argument values will result in a normalized date. For a strict conversion from a block, that will error out instead of normalizing, use make.

5. Comparisons

All comparators can be applied on dates: =, ==, <>, >, <, >=, <=, same?. In addition, min, max and sort are also supported.

Examples

3-Jul-2017/9:41:40+2:00 = 3-Jul-2017/5:41:40-2:00
== true

10/10/2017 < 1/1/2017
== false

max 10/10/2017 1/1/2017
== 10-Oct-2017

same? 1/1/1980 1-JAN-1980
== true

sort [1/1/2017 5/10/1999 3-Jul-2017/5:41:40-2:00 1/1/1950 1/1/1980/2:2:2]
== [1-Jan-1950 1-Jan-1980/2:02:02 5-Oct-1999 1-Jan-2017 3-Jul-2017/5:41:40-02:00]

6. Arithmetic

Supported math operations on dates include:

  • adding or subtracting values from any date field: the result is normalized.

  • adding or subtracting an integer value with a date value: interpreted as a number of days.

  • adding or subtracting a time value with a date value: will add/subtract it to/from the date’s time.

  • subtracting two date values: result is a signed number of days between those two dates.

  • using the difference function on two date values: result is the signed difference, as a time! value, between those two dates.

Examples

20-Feb-1980 + 50
== 10-Apr-1980

20-Feb-1980 + 3
== 23-Feb-1980

20-Feb-1980 - 25
== 26-Jan-1980

20-Feb-1980 + 100
== 30-May-1980

28-Feb-1980 + 20:30:45
== 28-Feb-1980/20:30:45

28-Feb-1980/8:30:00 + 20:30:45
== 29-Feb-1980/5:00:45

d: 20-Feb-1980
d/day: d/day + 50
== 10-Apr-1980

d: 20-Feb-1980
d/month: d/month + 5
== 20-Jul-1980

d: 28-Feb-1980/8:30:00
d/hour: d/hour + 48
== 1-Mar-1980/8:30:00

08/07/2017/10:45:00 - 20-Feb-1980/05:30:0
== 13653

difference 08/07/2017/10:45:00 20-Feb-1980/05:30:0
327677:15:00

7. Getting the current date

The now function returns the operating system’s current date and time (including timezone). All the date path accessors are available to now as refinements, with some additions:

  • /utc: get the date in UTC format.

  • /precise: get the time with higher precision (1/60th of a second on Windows, micro-seconds on Unix)

Examples

now
== 8-Jul-2017/18:32:25+08:00

now/year
== 2017

now/hour
== 18

now/month
== 7

now/day
== 8

now/hour
== 18

now/zone
== 8:00:00

now/utc
== 8-Jul-2017/10:32:25

8.1. Random

Syntax

random <date>

<date> : a date! value

Description

Returns a randomized date using the argument date as upper limit. If the argument date has no time/timezone component, the resulting date won’t have it either.

Examples

random 09/07/2017
== 18-May-1972

random 09/07/2017
== 13-Aug-0981

random 09/07/2017/12:00:00+8
== 28-Feb-0341/17:57:12+04:00

random 09/07/2017/12:00:00+8
== 13-Dec-1062/5:09:12-00:30

results matching ""

    No results matching ""