DateTime
About
This class is inspired by one of the most popular JavaScript date packages, dayjs. 🚀
DateTime
lets you create an object that represents a single point in time with millisecond precision between midnight on January 1st, 0 CE, and 23:59:59.999 on December 31st, 9999 CE.
Once you have a DateTime
, you can:
- Add or subtract days and/or time
- Compare it with another
DateTime
- Convert it to another timezone
- Convert it to/from UTC or local time
- Format it as a localized string with total flexibility
Instances of DateTime
are immutable. All functions that would change the value of a DateTime
return a new DateTime
instance.
IMPORTANT
Do not attempt to save DateTime
objects or JSON stringified objects to the database or pass them to remote machines, since they may be read later by a machine in a different timezone.
Instead, serialize them to a UTC string using .timestamp
and then deserialize them by passing the timestamp to the DateTime
constructor.
Timezone mode
Internally DateTime
is stored as UTC, along with:
- The offset from UTC at the moment represented by the
DateTime
- The timezone abbreviation
- The timezone name
DateTime
is always created in local mode, meaning that all functions that retrieve or display values operate in the local timezone. If you wish to retrieve or display UTC values, you can switch to UTC mode with .utc
property, and back to local mode with the .local
property.
// 2022-08-27T20:13:27.123-07:00 in PDT
// 2022-08-28T03:13:27.123Z in UTC
$dt:=cs.js.DateTime.new(!08/27/22!; ?20:13:27?; 123)
$date:=$dt.date // 2022-08-27
$date:=$dt.utc.date // 2022-08-28
$day:=$dt.day // 27
$day:=$dt.utc.day // 28
$time:=$dt.time // 20:13:27
$time:=$dt.utc.time // 03:13:27
$hour:=$dt.hour // 20
$hour:=$dt.utc.hour // 3
$timestamp:=$dt.timestamp // 2022-08-27T20:13:27.123-07:00
$timestamp:=$dt.utc.timestamp // 2022-08-28T03:13:27.123Z
Creation
constructor()
cs.js.DateTime.new()
cs.js.DateTime.new(epochTime : Real)
cs.js.DateTime.new(input : Text)
cs.js.DateTime.new(date : Date { ; time : Time { ; ms : Integer { ; timezone : Text }}})
cs.js.DateTime.new(
year : Integer; month : Integer; day : Integer
{ ; hour : Integer { ; minute : Integer { ; second : Integer { ; ms : Integer { ; timezone : Text }}}}}
)
cs.js.DateTime.new(config : Object)
cs.js.DateTime.new(dateTime : cs.js.DateTime)
Creates a new DateTime
instance, which is always in local mode. A DateTime
can be created in a variety of ways:
Current date/time
In the first form, a DateTime
is created with the current date, time, and milliseconds in the local timezone.
TIP
DateTime.now()
is a shortcut for the first constructor form.
From epoch time
In the second form, a DateTime
is created from a Unix epoch time in milliseconds.
TIP
This form is fully compatible with the result of the JavaScript Date.getTime()
method.
From a string
In the third form, input should be a string consisting of:
A date in the format
YYYY-MM-DD
.An optional 24-hour time in the format
HH:MM:SS
, separated from the date byT
.An optional millisecond value in the format
SSS
, separated from the time by.
.An optional timezone offset, which may either be
Z
to indicate UTC, or an offset in the format±HHMM
, with an optional:
separator between the hours and minutes.
If input is malformed, an error is thrown and the DateTime
is considered invalid.
From parts
In the fourth and fifth forms, you pass the constituent parts of DateTime
. Omitted parameters default to a zero value. If timezone is omitted, the local timezone at the given date and time is used.
In the sixth form, you pass an object with any of the following properties:
Property | Type |
---|---|
.date | Date |
.time | Time/Number |
.year | Number |
.month | Number |
.day | Number |
.hour | Number |
.minute | Number |
.second | Number |
.ms | Number |
.timezone | Text |
A few rules apply:
You must pass either
.date
, or.year
,.month
and.day
. If you pass.date
,.year
,.month
and.day
are ignored.The rest of the properties are optional. Omitted properties default to a zero/empty value.
If you pass
.time
,.hour
,.minute
, and.second
are ignored.
Passing a timezone
In any of the above forms, if a timezone is passed as a parameter or as a property of config, it should consist of either:
A valid IANA timezone abbreviation and timezone name, separated by
|
. If the abbreviation is unambiguous within an area such asEurope
, you may pass the area as the timezone name. For example,CET|Europe
is valid becauseCET
is unambiguous within the areaEurope
."UTC"
(no timezone name is necessary), in which case the input values are considered to be in UTC.
TIP
An easier and more flexible way to create a UTC DateTime
is to use DateTime.utc()
.
If the timezone is invalid or ambiguous, an error is thrown and the DateTime
is considered invalid.
Passing a timezone does not set the local timezone abbreviation and name. What it does do is to determine which timezone the given date and time belong to, and thus the UTC time they represent. For example, if the timezone is CET|Europe/Paris
, the UTC time will be one hour less than the given time.
DateTime
Copying a In the final form (the copy constructor), a copy of dateTime is created.
TIP
.clone()
is a shortcut for passing This
to the copy constructor.
The following errors are thrown if the constructor is called with invalid parameters:
Error | Cause |
---|---|
TypeError | The first parameter is an invalid type |
TypeError | The first parameter is a number, but the following two are not |
TypeError | hour is not a number |
TypeError | config contains .year but not .month and .day |
RangeError | timezone is invalid or ambiguous |
SyntaxError | input is malformed |
Examples
// First form
$dt:=cs.js.DateTime.new()
// Second form, all are valid
$dt:=cs.js.DateTime.new("2020-01-01")
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56")
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56.789")
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56Z") // UTC
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56.789Z") // UTC
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56.789-0800")
$dt:=cs.js.DateTime.new("2020-01-01T12:34:56.789-08:00")
// Third form, all are valid
$dt:=cs.js.DateTime.new(!2020-01-01!)
$dt:=cs.js.DateTime.new(!2020-01-01!; ?12:34:56)
$dt:=cs.js.DateTime.new(!2020-01-01!; ?12:34:56; 789)
// Date and time are UTC
$dt:=cs.js.DateTime.new(!2020-01-01!; ?12:34:56; 789; "UTC")
// The UTC time will be 12:34:56 +8 hours. This is independent of
// the local time.
$dt:=cs.js.DateTime.new(!2020-01-01!; ?12:34:56; 789; "PST|America/Los_Angeles")
// PST is unique within the "America" timezone area, this is also valid
$dt:=cs.js.DateTime.new(!2020-01-01!; ?12:34:56; 789; "PST|America")
// Values are considered to be UTC
$dt:=DateTime.utc("2020-01-01T12:34:56.789")
$dt:=DateTime.utc(!2020-01-01!; ?12:34:56; 789)
If invalid input is passed to the constructor, an error is thrown and the created DateTime
is considered invalid.
.clone()
.clone()
Returns a copy of this DateTime
. This is equivalent to passing This
to the copy constructor.
Properties
.date
.date : Date
Returns the local or UTC date of this DateTime
, depending on the timezone mode. This property is read-only.
.day
.day : Integer
Returns the local or UTC day of the month (1-31) of this DateTime
, depending on the timezone mode. This property is read-only.
.daysInMonth
.daysInMonth : Integer
Returns the number of days in the local or UTC month of this DateTime
, depending on the timezone mode. This property is read-only.
.epochTime
.epochTime : Real
Returns the number of milliseconds since January 1, 1970, 00:00:00 UTC. Negative values are returned for prior times. The value returned by this property can be passed directly to the JavaScript Date(value)
constructor.
This property is read-only.
.hour
.hour : Integer
Returns the local or UTC hour (0-23) of this DateTime
, depending on the timezone mode. This property is read-only.
.milliseconds
.milliseconds : Integer
Returns the milliseconds (0-999) of this DateTime
. This property is read-only.
.minute
.minute : Integer
Returns the local or UTC minute (0-59) of this DateTime
, depending on the timezone mode. This property is read-only.
.month
.month : Integer
Returns the local or UTC month (1-12) of this DateTime
, depending on the timezone mode. This property is read-only.
.second
.second : Integer
Returns the local or UTC second (0-59) of this DateTime
, depending on the timezone mode. This property is read-only.
.time
.time : Time
Returns the local or UTC time of this DateTime
, depending on the timezone mode. This property is read-only.
.valid
.valid : Boolean
Returns True
if this DateTime
is valid, False
otherwise. A DateTime
is considered invalid if it was created with invalid input, or if it was created with a timezone that does not exist.
IMPORTANT
The results of operating on an invalid DateTime
are undefined. It is up to you to check the validity of this DateTime
before using it.
.weekday
.weekday : Integer
Returns the local or UTC day of the week (1-7) of this DateTime
, depending on the timezone mode. This property is read-only.
.year
.year : Integer
Returns the local or UTC full year of this DateTime
, depending on the timezone mode. This property is read-only.
Manipulation
.add()
.add(years : Integer { ; months : Integer { ; days : Integer { ; time : Time }}}) : cs.js.DateTime
.add(amount : Integer; unit : String) : cs.js.DateTime
.add(amounts : Object) : cs.js.DateTime
Returns a new DateTime
adjusted by the given amounts.
The first form works just like the 4D Add to date
command but allows you to add time as well.
The second form allows you to specify a single unit of time to add. The unit parameter can be one of the following:
Unit | Shorthand |
---|---|
day | d |
week | w |
month | M |
year | y |
hour | h |
minute | m |
second | s |
NOTE
The full unit names may have a plural or singular form. For example, day
and days
are both valid.
The third form is an object which may have one or more properties which match the plural units listed above (e.g. .years
, .minutes
, etc.). Missing units are treated as zero.
If the parameters do not match any of the forms, a TypeError
is thrown.
Overflows or underflows adjust the next highest unit accordingly. For example:
$dt:=cs.js.DateTime.new(!2019-01-27!; ?23:59:59?)
$d2:=$dt.add(1; 1; 1; ?00:00:01?)
// $d2 => 2020-02-29 00:00:00 (2020 is a leap year)
$dt:=cs.js.DateTime.new(!2022-08-27!; ?23:59:59?)
$d2:=$dt.add(5, 'seconds')
// $d2 => 2022-08-28 00:00:04
$dt:=cs.js.DateTime.new(!2022-08-27!; ?23:59:59?)
$d2:=$dt.add(_.json("{ 'days': 1, 'hours': 2, 'seconds': 1 }"))
// $d2 => 2022-08-29 02:00:00
TIP
While you can add negative amounts, it is probably clearer to use .subtract()
instead.
.offset()
.offset(seconds : Integer) : cs.js.DateTime
Returns a new DateTime
with the given UTC offset applied. Note that the timezone will not be adjusted accordingly. This is useful when you need to display a DateTime
in a different timezone, but you don’t want to look up (or don’t have) the timezone abbreviation and name.
Example
// UTC offset is -7 hours
$dt:=cs.js.DateTime.new(!2022-03-30!; ?00:05:00?; 0; "PDT|America/Los_Angeles")
// We want to show the time in another timezone whose UTC offset is -4 hours
$offset:=[users]tzOffset
$formatted:=$dt.offset([users]tzOffset).format("LT")
// $formatted => 3:05 AM
.subtract()
.subtract(years : Integer { ; months : Integer { ; days : Integer { ; time : Time }}}) : cs.js.DateTime
.subtract(amount : Integer; unit : String) : cs.js.DateTime
.subtract(amounts : Object) : cs.js.DateTime
Returns a new DateTime
adjusted by the given amounts. This is the same as .add()
, but subtracts values instead of adding.
Queries
.compareWith()
.compareWith(datetime : cs.js.DateTime) : Integer
Compares this DateTime
with another, including date and time:
- If this
DateTime
is before datetime,-1
is returned. - If this
DateTime
is after datetime,1
is returned. - If they are equal,
0
is returned.
.diff()
.diff(dateTime : cs.js.DateTime { ; factorSeconds : Boolean }) : Object
Calculates the difference between this DateTime
and dateTime.
If factorSeconds is false (the default), the result is an object with the following properties:
{
"days": Integer;
"seconds: Integer;
"ms": Integer
}
If factorSeconds is true, the total difference in seconds is factored into hours, minutes, and seconds, and the result is an object with the following properties:
{
"days": Integer;
"hours": Integer;
"minutes": Integer;
"seconds: Integer;
"ms": Integer
}
.isAfter()
.isAfter(datetime : cs.js.DateTime) : Boolean
Returns whether this DateTime
is after datetime.
.isBefore()
.isBefore(datetime : cs.js.DateTime) : Boolean
Returns whether this DateTime
is before datetime.
.isSameAs()
.isSameAs(datetime : cs.js.DateTime) : Boolean
Returns whether this DateTime
is the same as datetime.
.isSameOrAfter()
.isSameOrAfter(datetime : cs.js.DateTime) : Boolean
Returns whether this DateTime
is the same as or after datetime.
.isSameOrBefore()
.isSameOrBefore(datetime : cs.js.DateTime) : Boolean
Returns whether this DateTime
is the same as or before datetime.
String conversion
.description()
.description() : Text
Returns a debug description of this DateTime
.
.format()
.format(format : Text) : Text
This function allows you to easily format this DateTime
with total flexibility. format is a string that specifies the contents and format of the output. The following formatting tokens are recognized:
Category | Token | Output |
---|---|---|
Month | M | 1 2 … 11 12 |
sM | Some as M , but padded with leading space for 1-9 | |
MM | 01 02 … 11 12 | |
MMM | Jan Feb … Nov Dec | |
MMMM | January February … November December | |
Day of Month | D | 1 2 … 30 31 |
sD | Same as D , but padded with leading space for 1-9 | |
Do | 1st 2nd … 30th 31st | |
DD | 01 02 … 30 31 | |
Day of Week | d | 1 2 … 6 7 |
dd | Su Mo … Fr Sa | |
ddd | Sun Mon … Fri Sat | |
dddd | Sunday Monday … Friday Saturday | |
Year | YY | 70 71 … 29 30 |
YYYY | 1970 1971 … 2029 2030 | |
At | @ | at (localized proposition used before a time) |
AM/PM | A | AM PM |
a | am pm | |
Hour | H | 0 1 … 22 23 |
HH | 00 01 … 22 23 | |
h | 1 2 … 11 12 | |
hh | 01 02 … 11 12 | |
Minute | m | 0 1 … 58 59 |
mm | 00 01 … 58 59 | |
Second | s | 0 1 … 58 59 |
ss | 00 01 … 58 59 | |
Millisecond | SSS | 000 001 … 998 999 |
Timezone | Z | -07:00 -06:00 … +06:00 +07:00 |
ZZ | -0700 -0600 … +0600 +0700 | |
z | PST (Timezone abbreviation) | |
zz | America/Los_Angeles (Timezone name) |
NOTE
The Do
(date ordinal) token uses the current locale’s ordinal function to format the day of the month.
The value that some tokens represent depends on the current timezone mode and the current locale.
To include text in format that is not a token (other than spaces), enclose it in []
. The []
is ignored, and the text within is passed through untouched.
In addition to the tokens listed above, you may also use format tokens in format. For a list of the localized format tokens that are built-in, see the .datetime.formats
object in the Locale file structure section.
Alternately, instead of tokens, you may also pass a custom format as format. Unlike format tokens, custom formats are not composable; format must match the custom format name exactly.
If format is empty, the result of This.toString()
is returned.
Examples
$dt:=cs.js.DateTime.new(!1931-08-27!)
$formatted:=$dt.format("dddd, MMMM Do YYYY, h:mm:ss a")
// => "Sunday, August 27th 1931, 12:00:00 am"
$now:=DateTime.now()
$formatted:=$now.format("[The time is now ]h:mm a [on ]dddd, MMMM Do")
// => "The time is now 3:27 pm on Friday, November 18th"
$formatted:=$dt.format("shortDate")
// => "11/18/22"
// You can also pass DateTime formats via _.format(),
// which are passed through to the DateTime.format() function.
$dt:=cs.js.DateTime.new(!2022-12-01!; ?10:00:00?)
$formatted:=_.format("${1|LWDOM @ lt z}"; $dt.tz("CST|America/Chicago"))
// => "Friday, December 1st at 10:00 am CST"
.formatUTCOffset()
.formatUTCOffset({ separator: Boolean }) : Text
Returns the UTC offset of this DateTime
in standard ISO format. If separator is true, :
is placed between the hours and minutes.
Examples
// Assuming the current timezone is America/Los_Angeles
$dt:=cs.js.DateTime.new(!2022-12-01!; ?10:00:00?)
$offset:=$dt.formatUTCOffset()
// => "-0800"
$offset:=$dt.formatUTCOffset(True)
// => "-08:00"
$offset:=$dt.tz("UTC|UTC").formatUTCOffset()
// => "+0000"
.timestamp
.timestamp : Text
Returns this DateTime
as a UTC timestamp in the format YYYY-MM-DDTHH:mm:ss.SSSZ
. This property is read-only.
.toString()
.toString({ format : Text }) : Text
Returns this DateTime
as a string:
If format is not empty, the result of
This.format($format)
is returned.If the timezone mode is "local", the string represents local date/time in the format
YYYY-MM-DDTHH:mm:ss.SSS±HHMM
.If the timezone mode is "utc", the string represents UTC date/time in the format
YYYY-MM-DDTHH:mm:ss.SSSZ
.
TIP
Remember that .toString()
will be used by js.component by default to convert this DateTime
to a string in any function that needs to do so. For example, _.format()
will call .toString()
for a placeholder if the value is a DateTime
, and pass any format along.
Examples
$dt:=cs.js.DateTime.new(!2022-12-01!;?12:00:00?; "CST|America/Chicago")
$str:=$dt.toString()
// => "2022-12-01T10:00:00.000-0800"
$str:=$dt.utc.toString()
// => "2022-12-01T18:00:00.000Z"
// Local timezone is PST
$message:=_.format("We will convene at ${1|LT z} on ${1|LWDOM} on zoom."; $dt)
// => "We will convene at 10:00 AM PST on Thursday, December 1st on zoom."
.toUTCString()
.toUTCString() : Text
Returns this DateTime
as a UTC string in the format YYYY-MM-DDTHH:mm:ss.SSSZ
.
Timezones
.local
.local : cs.js.DateTime
If this DateTime
is already in local mode, returns this DateTime
. Otherwise, returns a copy of this DateTime
with the timezone mode set to "local". This property is read-only.
.mode
.mode : Text
Returns the current timezone mode ("local" or "utc") for this DateTime
. This property is read-only.
.timezone
.timezone : Text
Returns .timezoneAbbrev
and .timezoneName
separated by |
. This property is read-only.
.timezoneAbbrev
.timezoneAbbrev : Text
Returns the local IANA timezone abbreviation for this DateTime
. This property is read-only.
.timezoneName
.timezoneName : Text
Returns the local IANA timezone name for this DateTime
. This property is read-only.
.tz()
.tz(timezone : Text) : cs.js.DateTime
Returns a copy of DateTime
but with the timezone offset specified by timezone, which should be in the standard <abbrev>|<name>
format used by the constructor.
If timezone does not specify a valid timezone, a RangeError
is thrown and the returned DateTime
will be in the same timezone as this DateTime
.
This function does not change the underlying UTC date/time. It only changes the timezone offset, and thus what is considered local time. This is primarily useful for displaying a DateTime
in a different timezone than the local timezone.
IMPORTANT
js.component currently does not know if the specified timezone actually corresponds to the timezone at the date and time of this DateTime
. For example, specifying a Daylight Saving Time timezone for a DateTime
that is in Standard Time will result in a timezone offset — and thus local times — that are incorrect.
Example
$dt:=cs.js.DateTime.new(!2022-11-11!;?08:31:00?) // PST|America/Los_Angeles
$ts:=$dt.toString() // => "2022-11-11T08:31:00.000-0800"
$dt2:=$dt.tz("EET|Europe/Kyiv")
$ts2:=$dt2.toString() // => "2022-11-11T18:31:00.000+0200"
// Careful! This is the wrong timezone for this date/time.
// The correct abbreviation for this date/time is "PST".
$dt3:=$dt.tz("PDT|America/Los_Angeles")
// Should be "2022-11-11T08:31:00.000-0800" this date/time
$ts3:=$dt3.toString() // => "2022-11-11T09:31:00.000-0700"
// The timezone name is necessary because CST is ambiguous otherwise
$dt:=cs.DateTime.new(!2022-12-01!; ?12:00:00?; 0; "CST|America/Chicago")
// $dt is in CST, but the local timezone is PST.
// If we convert to a string, it shows PST time, not CST time.
$formatted:=_.format("${1|dddd, MMMM Do} at ${1|h:mm a}"; $dt)
// => "Thursday, December 1st at 10:00 am"
// To show CST time, we need to convert to CST first
$formatted:=_.format(\
"${1|dddd, MMMM Do} at ${1|h:mm a} CST"; \
$dt.tz("CST|America/Chicago"))
.utc
.utc : cs.js.DateTime
If this DateTime
is already in UTC mode, returns this DateTime
. Otherwise, returns a copy of this DateTime
with the timezone mode set to "utc". This property is read-only.
.utcOffset
.utcOffset : Integer
Returns the offset in seconds of the local time zone from UTC at the moment in time represented by this DateTime
. This property is read-only.
Examples
$dt:=cs.js.DateTime.new(!2021-01-01!) // America/Los_Angeles PST
$dt.timezoneOffset // -28800 (-08:00)
$dt:=cs.js.DateTime.new(!2021-07-01!) // America/Los_Angeles PDT
$dt.timezoneOffset // -25200 (-07:00)
i18n
.loc()
.loc() : Text
.loc(locale : Text) : cs.js.DateTime
Shorthand for .locale
.
.locale()
.locale() : Text
.locale(locale : Text) : cs.js.DateTime
With no parameters, returns the current locale for this DateTime
.
With a locale parameter, returns a copy of this DateTime
with the locale set to the resolved locale.
.localeData
.localeData : Object
Returns the locale data for this DateTime
’s locale. The returned object should not be modified.