Specify Time Zones

In MATLAB®, you can specify time zones for `datetime` arrays. This example shows how to create and work with datetime arrays that include time zones.

A time zone is a geographic area that observes a uniform standard time. Time zones include time offsets from Coordinated Universal Time (UTC), time offsets from daylight saving time (DST), and a set of historical changes to those offsets. To set a time zone and calculate time zone offsets, the `datetime` data type uses code and data provided by the Internet Assigned Numbers Authority (IANA) in the IANA Time Zone Database.

Display and Search Table of Time Zones

To see a complete table of time zones that are known to MATLAB, use the `timezones` function. Every row of the table shows the name of a time zone, its geographic area, its offset from UTC, and its offset due to DST. For time zones that observe DST, the DST offset is applied according to the current and historical rules for those time zones.

`AllTimeZones = timezones`
```AllTimeZones=457×4 table Name Area UTCOffset DSTOffset ______________________ ______ _________ _________ {'Africa/Abidjan' } Africa 0 0 {'Africa/Accra' } Africa 0 0 {'Africa/Addis_Ababa'} Africa 3 0 {'Africa/Algiers' } Africa 1 0 {'Africa/Asmera' } Africa 3 0 {'Africa/Bamako' } Africa 0 0 {'Africa/Bangui' } Africa 1 0 {'Africa/Banjul' } Africa 0 0 {'Africa/Bissau' } Africa 0 0 {'Africa/Blantyre' } Africa 2 0 {'Africa/Brazzaville'} Africa 1 0 {'Africa/Bujumbura' } Africa 2 0 {'Africa/Cairo' } Africa 2 1 {'Africa/Casablanca' } Africa 0 1 {'Africa/Ceuta' } Africa 1 1 {'Africa/Conakry' } Africa 0 0 ⋮ ```

To see the version of the IANA Time Zone Database that MATLAB uses, return the second output from `timezones`.

`[~,DBversion] = timezones`
```DBversion = '2023c' ```

To find the name of a time zone, you can search the `Name` variable of the table of time zones. To find the whole name when you know part of the name, you can use the `contains` function. For example, find the name of the time zone that corresponds to New York. Replace space characters with underscores in your search string.

```TFindex = contains(AllTimeZones.Name,"New_York"); NewYorkZone = AllTimeZones.Name(TFindex)```
```NewYorkZone = 1x1 cell array {'America/New_York'} ```

Display the corresponding row of the time zones table. To match the exact name of the time zone, use the `matches` function.

```TFindex = matches(AllTimeZones.Name,NewYorkZone); AllTimeZones(TFindex,:)```
```ans=1×4 table Name Area UTCOffset DSTOffset ____________________ _______ _________ _________ {'America/New_York'} America -5 1 ```

Create `datetime` Values with Time Zones

Every `datetime` array has a time zone property. By default, this property is not set, which means the resulting `datetime` array is unzoned. You can use unzoned `datetime` arrays for local time calculations in which you do not need to consider DST or local times in other time zones.

For example, create a `datetime` value for the current time, and display its `TimeZone` property. The current date and time values come from your system clock. Without a time zone, the `datetime` value cannot calculate the time zone offset relative to UTC.

`D = datetime("now")`
```D = datetime 12-Feb-2024 22:35:49 ```
`D.TimeZone`
```ans = 0x0 empty char array ```

There are two ways to set the time zone of a `datetime` array. The first way is to specify the `TimeZone` name-value argument of the `datetime` function when creating the `datetime` array. Specifying this argument sets the value of the `TimeZone` property.

`D = datetime("now",TimeZone="America/New_York")`
```D = datetime 12-Feb-2024 22:35:49 ```
`D.TimeZone`
```ans = 'America/New_York' ```

The second way is to assign a value to the `TimeZone` property after you have created the `datetime` array.

`D = datetime("now")`
```D = datetime 12-Feb-2024 22:35:49 ```
`D.TimeZone = "America/New_York"`
```D = datetime 12-Feb-2024 22:35:49 ```

You can also specify the `TimeZone` property as a duration that is just a fixed time zone offset from UTC. Such an offset does not incorporate any current or historical offset rules, such as daylight saving time.

For example, specify a time zone offset that is five hours behind UTC. This offset is the same as the UTC offset for `America/New_York`, but it does not include any offset for daylight saving time.

`D = datetime("now",TimeZone="-05:00")`
```D = datetime 12-Feb-2024 22:35:49 ```
`D.TimeZone`
```ans = '-05:00' ```

You can specify `TimeZone` as any value in this list:

• `""` — No time zone

• Time zone name — Time zone from IANA Time Zone Database

• Time zone offset in `+HH:mm` or `-HH:mm` format — Fixed offset from UTC

• Time zone offset as `duration` scalar (since R2024a) — Fixed offset from UTC, specified using the `hours`, `minutes`, `seconds`, or `duration` function

• `"UTC"` — Coordinated Universal Time

• `"UTCLeapSeconds"` — Coordinated Universal Time, but also incorporating leap seconds

• `"local"` — IANA time zone that corresponds to the system time zone

Specify Formats That Include Time Zone Offsets

The default format for `datetime` arrays does not include the time zone. However, you can include the time zone offset in the format by using the `z` or `Z` identifiers.

For example, change the format to include the date, time, and time zone offset using `z`. The `z` identifier specifies the short localized version of the offset. Its behavior depends on your locale.

```D = datetime("now", ... TimeZone="America/New_York", ... Format="dd-MMM-uuuu HH:mm:ss z")```
```D = datetime 12-Feb-2024 22:35:49 EST ```

The `Z` identifier specifies a basic format that displays the offset as hours, minutes, and optionally seconds.

`D.Format = "dd-MMM-uuuu HH:mm:ss Z"`
```D = datetime 12-Feb-2024 22:35:49 -0500 ```

You can also specify the long UTC format. For a complete list of time zone offset identifiers, see `datetime`.

`D.Format = "dd-MMM-uuuu HH:mm:ss ZZZZ"`
```D = datetime 12-Feb-2024 22:35:49 UTC-05:00 ```

Encode Same Time in Different Time Zone

If you change the time zone of a `datetime` value, it still encodes the same point in time. If the offset from UTC changes, then the date and time values change in a way that compensates for the change in the offset.

For example, create a `datetime` value in the New York time zone, and format it to display the time zone offset.

```D = datetime("today", ... TimeZone="America/New_York", ... Format="dd-MMM-uuuu HH:mm:ss z")```
```D = datetime 12-Feb-2024 00:00:00 EST ```

Then change its time zone to the zone for Los Angeles. The date and time values change to encode the same point in time in a different time zone.

`D.TimeZone = "America/Los_Angeles"`
```D = datetime 11-Feb-2024 21:00:00 PST ```

Compare `datetime` Values with Different Time Zones

If you compare `datetime` values that have different time zones, then the comparison takes the time zone offsets into account. However, you cannot compare zoned and unzoned `datetime` arrays because an unzoned array has no known time zone offset. Both arrays must be zoned or unzoned.

For example, create a `datetime` value. Then copy it and change its time zone.

```NYTime = datetime("today", ... TimeZone="America/New_York", ... Format="dd-MMM-uuuu HH:mm:ss z")```
```NYTime = datetime 12-Feb-2024 00:00:00 EST ```
```LATime = NYTime; LATime.TimeZone = "America/Los_Angeles"```
```LATime = datetime 11-Feb-2024 21:00:00 PST ```

Compare the two values using the `==` operator. The values are equal because they encode the same point in time.

`AreTimesEqual = NYTime == LATime`
```AreTimesEqual = logical 1 ```

There is no actual difference between the two times.

`TimeDiff = LATime - NYTime`
```TimeDiff = duration 00:00:00 ```

Then add two hours to the Los Angeles time.

`LATime = LATime + hours(2)`
```LATime = datetime 11-Feb-2024 23:00:00 PST ```

Compare the two times. Despite their date and time values, the time in Los Angeles occurs later than the time in New York.

`IsLATimeLater = LATime > NYTime`
```IsLATimeLater = logical 1 ```

The difference between the times is two hours.

`TimeDiff = LATime - NYTime`
```TimeDiff = duration 02:00:00 ```

Concatenate `datetime` Arrays with Different Time Zones

The `TimeZone` property applies to every element in a `datetime` array. However, you can concatenate `datetime` arrays that have different time zones. The concatenated array has the same time zone as the first array. You cannot concatenate zoned and unzoned `datetime` arrays because the unzoned array has no known time zone offset. Both arrays must be zoned or unzoned.

For example, concatenate `NYTime` and `LATime`. The result has the time zone for New York.

`combinedNYZone = [NYTime LATime]`
```combinedNYZone = 1x2 datetime 12-Feb-2024 00:00:00 EST 12-Feb-2024 02:00:00 EST ```

Then concatenate in the reverse order. The result has the time zone for Los Angeles.

`combinedLAZone = [LATime NYTime]`
```combinedLAZone = 1x2 datetime 11-Feb-2024 23:00:00 PST 11-Feb-2024 21:00:00 PST ```

Account for Leap Seconds Using Special Time Zone

A leap second is a one-second adjustment that is applied to UTC. Leap seconds were introduced in 1972 to account for the difference between precise time based on atomic clocks and observed solar time, which varies due to small changes in earth's rotation rate. Those changes do not come in a predictable pattern, so leap seconds have been declared as needed. The leap second data incorporated into MATLAB is provided by the International Earth Rotation and Reference Systems Service (IERS). For more information, see the IERS Bulletins.

The `datetime` data type has a special time zone that accounts for leap seconds. For any calculations or comparisons that involve leap seconds, specify the time zone as `"UTCLeapSeconds"`. When you use this time zone, the default format includes the date, time, and the letter `Z` to indicate UTC, according to the ISO 8601 standard.

`todayLS = datetime("today",TimeZone="UTCLeapSeconds")`
```todayLS = datetime 2024-02-13T00:00:00.000Z ```

You cannot combine or compare `datetime` arrays when one array has leap seconds and the other array does not.

One way to see the effect of leap seconds is to calculate the length of time between today's date and January 1, 1972, in the `UTC` and `UTCLeapSeconds` time zones. First calculate the duration in the `UTC` zone. The duration is shown in `hh:mm:ss` format.

`durationWithoutLS = datetime("today",TimeZone="UTC") - datetime(1972,1,1,TimeZone="UTC")`
```durationWithoutLS = duration 456864:00:00 ```

Then calculate the duration in the `UTCLeapSeconds` zone. The difference between the two durations is due to the cumulative effect of the leap seconds declared since 1972.

`durationWithLS = datetime("today",TimeZone="UTCLeapSeconds") - datetime(1972,1,1,TimeZone="UTCLeapSeconds")`
```durationWithLS = duration 456864:00:27 ```

To see all the leap seconds known to MATLAB and the dates they were declared, use the `leapseconds` function.

`LS = leapseconds`
```LS=27×2 timetable Date Type CumulativeAdjustment ___________ ____ ____________________ 30-Jun-1972 + 1 sec 31-Dec-1972 + 2 sec 31-Dec-1973 + 3 sec 31-Dec-1974 + 4 sec 31-Dec-1975 + 5 sec 31-Dec-1976 + 6 sec 31-Dec-1977 + 7 sec 31-Dec-1978 + 8 sec 31-Dec-1979 + 9 sec 30-Jun-1981 + 10 sec 30-Jun-1982 + 11 sec 30-Jun-1983 + 12 sec 30-Jun-1985 + 13 sec 31-Dec-1987 + 14 sec 31-Dec-1989 + 15 sec 31-Dec-1990 + 16 sec ⋮ ```

The second output returns the IERS Bulletin C version number of the leap second data used in MATLAB.

`[~,LSvers] = leapseconds`
```LSvers = 66 ```