Skip to main content

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.

workingDateTimeObjects1.png

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

MMM d, yyyy HH:mm:ss a

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

[[myDateTime = parseDateTime('2021-01-03T10:00+06:00[Europe/Paris]')]]

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

'2021-10-31'

Date-only value.

'07:30'

Time-only value.

'16:30'

Time-only value.

'16:30:24'

Time-only value (includes seconds).

'16:30:24.1234'

Time-only value (includes fractional seconds).

'2021-10-31T16:30'

Date + time value.

'2021-10-31T16:30:24'

Date + time value (includes seconds).

'2021-10-31T16:30:24.1234'

Date + time value (includes fractional seconds).

'2021-10-31T16:30+01:00'

Date + time value with offset (+1 hour).

'2021-10-31T16:30-01:00'

Date + time value with offset (-1 hour).

'2021-10-31T16:30-01:30:15'

Date + time value with offset (-1 hour, 30 minutes, and 15 seconds).

'2021-10-31T16:30Z[Europe/Paris]'

Date + time value with a zero offset and regional timezone.

'2021-10-31T16:30+02:00[Europe/Paris]'

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

[[parseDateTime('2018-12-12') > parseDateTime('2018-12-13')]]

False

[[parseDateTime('2018-12-12') > parseDateTime('2018-11-12')]]

True

[[parseDateTime('2018-12-12') <= parseDateTime('2018-12-12')]]

True

[[parseDateTime('2018-12-12') == parseDateTime('2018-11-12')]]

False

TIME-ONLY COMPARISONS

Comparison

Result

[[parseDateTime('10:40') > parseDateTime('10:10')]]

True

[[parseDateTime('10:40') > parseDateTime('10:50')]]

False

[[parseDateTime('10:40:20') == parseDateTime('10:40')]]

False

[[parseDateTime('10:40:00') == parseDateTime('10:40')]]

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 is the day after dateTime2.

[[
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.