Working with datetime objects
Datetime objects are objects that represent either a date, a time, or both a date and time.
You can compare datetime objects and use them in calculations — for example, you can add a duration, subtract a duration, or calculate the difference between two datetimes.
Index
Creating datetime objects
Datetime objects are created from string representations — e.g. "2020-04-01" or "Apr 1, 2020 12:00" — in your data. If the string value is in an automatically recognized datetime pattern, you can perform the conversion using either of these ATL functions:
Note that when you pass a string in an automatically recognized pattern into a function or expression that expects a datetime object, Studio implicitly creates a datetime object. This means converting with a function may be unnecessary.
Similarly, if your CSV data file contains a column of string values in an automatically recognized datetime pattern, the value variable created for that column (in "Describe Each Row" and "Describe Row in Context" projects) will return a datetime object. You can check the variable type in your project's Variables View — it will show DATETIME rather than STRING.
If your string is NOT in an automatically recognized pattern, you can convert that string to a datetime object by using the parseDateTime function. To do this, specify the pattern of the input string in the second parameter.
ATL in Script | Result |
---|---|
[[ stringValue = '02/04/2020'; dateTimeObject = parseDateTime(stringValue, 'dd/MM/yyyy'); ]] | Apr 2, 2020 |
You can then pass the created object into another datetime function. For example:
ATL in Script | Result |
---|---|
[[ stringValue = '02/04/2020'; dateTimeObject = parseDateTime(stringValue, 'dd/MM/yyyy'); formatDateTime(dateTimeObject, 'd MMMM yyyy') ]] | 2 April 2020 |
Note
The ATL [[formatDateTime('02/04/2020', 'd MMMM yyyy')]]
returns an error. The string ('02/04/2020'
) is NOT in a recognized pattern, so Studio does not recognize it as a datetime object.
Displaying datetime objects
By default, Studio prints datetime objects by applying this format pattern:
Default Format Pattern |
---|
|
Here are some examples:
Type | Displayed As |
---|---|
Date only | Oct 31, 2021 |
Time only | 10: 35:45 AM |
Date + time | Oct 31, 2021 10:35:45 AM |
To change the display format, use the formatDateTime function and specify a pattern.
ATL in Script | Result |
---|---|
[[myDate = parseDateTime('2021-10-31')]] | Oct 31, 2021 |
[[ myDate = parseDateTime('2021-10-31'); formatDateTime(myDate, 'dd.MM.yyyy') ]] | 31.10.2021 |
[[ myDate = parseDateTime('2021-10-31'); formatDateTime(myDate,'EEEE, dd MMMM yyyy') ]] | Sunday, 31 October 2021 |
[[ myDateTime = parseDateTime('2021-10-31T14:00'); formatDateTime(myDateTime,'d/MM/yyyy HH:mm') ]] | 31/10/2021 14:00 |
Tip
See the formatDateTime topic for more detailed guidance and examples.
Offsets and timezones
A datetime can include an offset indicating its offset from Coordinated Universal Time (UTC). For example, '2021-10-31T14:00-05:00'
represents a local time (in New York, for example) five hours behind UTC. When it's 14:00 in New York, it's 19:00 in UTC.
Studio prints these datetimes to show the local time. For example:
ATL in Script | Result |
---|---|
[[myDateTime = parseDateTime('2021-10-31T14:00-05:00')]] | Oct 31, 2021 2:00:00 PM |
To print the offset, use formatDateTime and include XXX
in the format pattern.
ATL in Script | Result |
---|---|
[[ myDateTime = parseDateTime('2021-10-31T14:00-05:00'); formatDateTime(myDateTime, "d MMM, yyyy HH:mm:ss XXX") ]] | 31 Oct, 2021 14:00:00 -05:00 |
Similarly a datetime can include a timezone ID. To print this, use formatDateTime and include VV
in the format pattern.
ATL in Script | Result |
---|---|
[[myDateTime = parseDateTime('2021-10-31T14:00z[America/New_York]')]] | Oct 31, 2021 10:00:00 AM |
[[ myDateTime = parseDateTime('2021-10-31T14:00z[America/New_York]'); formatDateTime(myDateTime, "d MMM, yyyy HH:mm:ss a VV") ]] | 31 Oct, 2021 10:00:00 AM America/New_York |
You can use getTimeZone to get the offset or timezone only.
ATL in Script | Result |
---|---|
[[ myDateTime = parseDateTime('2021-10-31T14:00-05:00'); getTimeZone(myDateTime) ]] | -05:00 |
[[ myDateTime = parseDateTime('2021-10-31T14:00z[America/New_York]'); getTimeZone(myDateTime) ]] | America/New_York |
Automatically recognized datetime patterns
Studio recognizes and converts a string to a datetime object when it matches one of the following patterns:
PATTERN 1 — DATE-ONLY VALUES
yyyy-MM-dd
Date-only values must have three fields — year, month, and day — separated by hyphens in the order shown above.
PATTERN 2 — TIME-ONLY VALUES
HH:mm:ss.SSSSSSSSS
Time-only values must have hours and minutes fields; other fields are optional.
You may include fractional seconds up to nine decimal places.
PATTERN 3 — DATE + TIME VALUES
yyyy-MM-ddTHH:mm:ss.SSSSSSSSS
The date must have three fields (year, month, and day), and the time must have at least the hours and minutes fields.
You may include fractional seconds up to nine decimal places.
Tip
The T
character is a date-time delimiter. If your string uses T
in a non-recognized pattern — e.g. '21/03/2021T08:00'
— you must enclose it within single quotation marks when you convert it using the parseDateTime function.
[[dateTimeString = '21/03/2021T08:00'; parseDateTime(dateTimeString, "dd/MM/yyyy'T'HH:mm")]]
To avoid syntax errors, you must also enclose your entire format string within double quotation marks.
PATTERN 4 — DATE + TIME VALUES WITH A TIME OFFSET
yyyy-MM-ddTHH:mm:ss.SSSSSSSSSXXX
The date must have three fields (year, month, and day), and the time must have at least the hours and minutes fields.
The time offset (XXX) an be hours-only (e.g. +05) or hours + minutes (e.g. -05:30). Alternatively, you can give the letter
Z
to represent a zero-hour offset — i.e. the UTC timezone.
PATTERN 5 — DATE + TIME VALUES WITH GEOGRAPHIC TIMEZONE ID
yyyy-MM-ddTHH:mm:ss.SSSSSSSSSXXX[zone-ID]
The date must have three fields (year, month, and day), and the time must have at least the hours and minutes fields.
The time offset (XXX) can be hours-only (e.g. +05) or hours + minutes (e.g. -05:30). Alternatively, you can give the letter
Z
to represent a zero-hour offset — i.e. the UTC timezone. You must include an offset before the timezone.The ID is a regional timezone ID from the tz database (sometimes called the IANA Time Zone Database) . You must give the ID inside square brackets. The ID is in the form Region/City (e.g. Europe/Paris) — see Oracle’s list of timezone IDs for a complete list.
IMPORTANT: The offset and timezone should be equivalent. If not, Studio first applies the offset to the time to calculate the time instant (the UTC time), then translates that to the equivalent for the given timezone. For example:
ATL in Script | Result |
---|---|
| Jan 3, 2021 5:00:00 AM |
Remember that the time 10:00+06:00
represents a local time six hours ahead of UTC. Therefore, 10:00 in this local time translates to 04:00 UTC. The Paris equivalent is 05:00 because Paris is one hour ahead of UTC.
PATTERN KEY
yyyy = year MM = month dd = day T = delimiter for time HH = hours (24-hour clock) mm = minutes ss = seconds SSSSSSSSS = fractions of seconds XXX = time offset Z = zero time offset [zone-ID] = zone ID — see Oracle’s list of timezone IDs |
EXAMPLES OF STRINGS IN RECOGNIZED PATTERNS
String | Description |
---|---|
| Date-only value. |
| Time-only value. |
| Time-only value. |
| Time-only value (includes seconds). |
| Time-only value (includes fractional seconds). |
| Date + time value. |
| Date + time value (includes seconds). |
| Date + time value (includes fractional seconds). |
| Date + time value with offset (+1 hour). |
| Date + time value with offset (-1 hour). |
| Date + time value with offset (-1 hour, 30 minutes, and 15 seconds). |
| Date + time value with a zero offset and regional timezone. |
| Date + time value with an offset (+2 hours) and regional timezone. |
Tip
If your data contains datetimes that don't match one of the above patterns, Studio treats them as strings. Remember, you can convert strings to datetime objects by using parseDateTime.
Comparing datetime objects
As with numbers, you can compare dates and times by writing ATL statements with standard logical operators (==
, !=
, >
, >=
, <
, <=
). One datetime value is considered less than another if it occurs earlier. For example, a date in May 2021 is considered less than a date in June 2021. Similarly, if two times are on the same day, the earlier time is the lesser.
When a string value is in an automatically recognized pattern, Studio converts it to a datetime object for the comparison.
ATL in Script | Result |
---|---|
[[ dateTime1 = parseDateTime('06/05/19 12:30', 'dd/MM/yy HH:mm'); dateTime2 = '2019-05-06T12:30'; dateTime1 == dateTime2 ]] | True |
Both dateTime1
and dateTime2
return a datetime object. dateTime1
is created by using the parseDateTime function, but this is not required for dateTime2
because the string '2019-05-06T12:30'
is an automatically recognized datetime pattern.
Comparing datetimes using a conditional statement
Assume a "Describe Each Row" project with this sample data:
Name | BirthDate | |
---|---|---|
Row 1 | Andy | 1982-02-26 |
Row 2 | Peter | 1899-12-25 |
The values in the BirthDate column are strings in the automatically recognized pattern for date-only values. Therefore, Studio automatically converts these to datetime objects. No string-to-datetime conversion is required.
Here's how you might use a conditional statement in your script:
ATL in Script | Row 1 Result | Row 2 Result |
---|---|---|
[[Name]] is [[if(BirthDate < '1950-01-01'){prehistoric} elseif(BirthDate < '2000-01-01'){middle-aged} else{still young}]]. | Andy is middle-aged. | Peter is prehistoric. |
Note
The conditional compares the BirthDate value against a constant (first '1950-01-01'
and then, if required, '2000-01-01'
). Both constants are strings written in an automatically recognized pattern.
Rules for datetime comparisons
Since there are different types of datetime object — date-only, time-only, date + time — there are rules to remember for comparisons:
When one object is date + time and the other is date-only, Studio assumes the time for the date-only object is 00:00:00. For example,
'2021-03-24T23:00:00' > '2021-03-24'
is treated as'2021-03-24T23:00:00' > '2021-03-24T00:00:00'
.When one object is date + time and the other is time-only, Studio assumes the time-only object has the same date as the date + time object. For example,
'2021-03-24T23:00:00' > '21:00:00'
is treated as'2021-03-24T23:00:00' > '2021-03-24T21:00:00'
.When one object has an offset + timezone and the other is a local datetime, Studio assumes that the local datetime has the same offset + timezone as the zoned datetime. For example,
'2021-03-24T23:00:00Z[Europe/London]' > '2021-03-24T21:00:00'
is treated as'2021-03-24T23:00:00Z[Europe/London]' > '2021-03-24T21:00:00Z[Europe/London]'
.You can't compare a time-only value with a date-only value. In such comparisons, Studio returns a warning and compares the two values as strings. For example, comparing
'2021-03-24'
and'21:00:00'
produces this warning:MINOR: Incompatible types: A direct comparison cannot be made between the Date 'Mar 24, 2021' and the Time '9:00:00 PM' because they are of different types. A string comparison has been used instead.
Tip
Use the dateTimeDifference function if you want the actual difference between two datetimes.
Examples
DATE-ONLY COMPARISONS
Comparison | Result |
---|---|
| False |
| True |
| True |
| False |
TIME-ONLY COMPARISONS
Comparison | Result |
---|---|
| True |
| False |
| False |
| True |
Note
Studio processes '10:40'
as '10:40:00'
. Note that these values are NOT considered equal if you compare them as strings rather than as datatime objects.
DATETIME COMPARISONS
Comparison | Result | Notes |
---|---|---|
[[ dateTime1 = parseDateTime('2021-12-12T08:00:00'); dateTime2 = parseDateTime('2021-12-11T10:00:00'); dateTime1 < dateTime2 ]] | False |
|
[[ dateTime1 = parseDateTime('2021-12-12'); dateTime2 = parseDateTime('2021-12-12T00:00:00'); dateTime1 == dateTime2 ]] | True | When you compare a date-only value with a date + time value, Studio assumes the time for the date-only object is 00:00:00. |
[[ dateTime1 = parseDateTime('05:00'); dateTime2 = parseDateTime('2021-12-12T05:00'); dateTime1 == dateTime2 ]] | True | When you compare a time-only value with a date + time value, Studio assumes the time-only object has the same date as the date + time object. |
[[ dateTime1 = parseDateTime('09:41:25'); dateTime2 = parseDateTime('2000-01-01'); dateTime1 < dateTime2 ]] | True | You cannot compare a date-only value with a time-only value. In this case, Studio throws a MINOR warning to inform you it has compared the values as strings rather than datetimes. |
DATETIME WITH OFFSET/TIMEZONE COMPARISONS
Two datetime objects with different offsets/timezones are never regarded as equal, even if they represent the same time in UTC.
ATL in Script | Result |
---|---|
[[ dateTime1 = '2021-07-04T18:00+01:00[Europe/London]'; dateTime2 = '2021-07-04T13:00-04:00[America/New_York]'; dateTime1 == dateTime2 ]] | False |
Therefore, when comparing datetime objects with offsets/timezones, use dateTimeDifference to calculate the difference.
ATL in Script | Result |
---|---|
[[ dateTime1 = '2021-07-04T18:00+01:00[Europe/London]'; dateTime2 = '2021-07-04T13:00-04:00[America/New_York]'; dateTimeDifference(dateTime1,dateTime2) == 0 ]] | True |
If the difference is zero — as above — the two datetimes represent equivalent times in UTC.
Adding and subtracting durations
You can use the +
and -
operators to add or subtract a duration (in seconds) from a datetime object. The duration can be a number or an expression that evaluates to a number. Examples of both are shown below.
ATL in Script | Result | Note |
---|---|---|
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime + 60 ]] | Dec 25, 2021 8:01:00 AM | 60 seconds added. |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime - 60 ]] | Dec 25, 2021 7:59:00 AM | 60 seconds subtracted |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime + (60 * 60 * 24) ]] | Dec 26, 2021 8:00:00 AM | One day added. |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime - (60 * 60 * 24 * 5) ]] | Dec 20, 2021 8:00:00 AM | Five days subtracted. |
Important
The duration is always added or subtracted in seconds. The last two examples above use an arithmetic expression to calculate a certain duration in seconds. For example, (60 * 60 * 24)
calculates the number of seconds in one day.
Alternatively, use parseDuration, which takes a string representing a duration and returns a number expressing that duration in seconds.
ATL in Script | Result |
---|---|
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime + parseDuration('13 days','d') ]] | Jan 7, 2022 8:00:00 AM |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime - parseDuration('10 weeks','w') ]] | Oct 16, 2021 8:00:00 AM |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); dateTime + parseDuration('1 year, 1 day and 1 hour','ydh') ]] | Dec 26, 2022 9:00:00 AM |
You can also use addToDateTime or subtractFromDateTime.
ATL in Script | Result |
---|---|
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); addToDateTime(dateTime,'1 year 1 day and 1 hour','ydh') ]] | Dec 26, 2022 9:00:00 AM |
[[ dateTime = parseDateTime('2021-12-25T08:00:00'); subtractFromDateTime(dateTime,'1 year 1 day and 1 hour','ydh') ]] | Dec 24, 2020 7:00:00 AM |
Other datetime functions
Studio includes a large number of datetime functions, many of which are not covered in this topic. These simplify tasks such as:
retrieving a specific part of a datetime (e.g. the year only)
converting durations from seconds to another time unit (e.g. seconds to days)
converting numbers to month names in a chosen language (e.g. 1 = "lundi" in French).
Tip
See the Datetime functions topic for a comprehensive index.