Dates and times

Back to Climate Data Tools Contents

There are several different ways to work with dates and times in Matlab. This tutorial reviews the different date formats and discusses the relative strengths and weaknesses associated with each in the context of Earth science data.

Contents

Intro and Overview

As an example, we'll consider the way time is packaged in NetCDF format. Of course, the simplest way to load times from NetCDF files is to use the CDT function ncdateread, but this tutorial concerns what's going on behind the scenes of ncdateread, so we'll start with the raw time format as it's packaged in the example .nc file.

Begin by reading the time array:

t = ncread('ERA_Interim_2017.nc','time')
t =
  12×1 int32 column vector
   1025628
   1026372
   1027044
   1027788
   1028508
   1029252
   1029972
   1030716
   1031460
   1032180
   1032924
   1033644

At this point, you may feel somewhat bewildered. What are all those numbers? Use ncdisp to get some insight:

ncdisp('ERA_Interim_2017.nc','time')
Source:
           /home/chad/Documents/MATLAB/github/cdt/cdt_data/ERA_Interim_2017.nc
Format:
           64bit
Dimensions:
           time = 12    (UNLIMITED)
Variables:
    time
           Size:       12x1
           Dimensions: time
           Datatype:   int32
           Attributes:
                       units     = 'hours since 1900-01-01 00:00:00.0'
                       long_name = 'time'
                       calendar  = 'gregorian'

That tells us the units of time are

units = 'hours since 1900-01-01 00:00:00.0'

Sometimes the units might be days since 1971 or years since the Big Bang or seconds since I was born, so always be sure to check the units.

Time in units of hours since the year 1900 is not very intuitive to understand, so I recommend developing a habit of using either the datenum or datetime format consistently. Matlab makes it pretty easy to switch between datenum and datetime formats, but they each have their strengths and weaknesses. Here's a breakdown:

For our example file, remember that t represents the number of hours since the strike of midnight on New Years Day, 1900. That's what all those numbers in t are.

datenum

To convert those hours to datenum format, use 1900,1,1 as the date and put t in the hours place.

Also, the time variable in the NetCDF file was in int32 format, which datenum does not accept. So convert t to double when calling datenum:

t = datenum(1900,1,1,double(t),0,0)
t =
     736696.50
     736727.50
     736755.50
     736786.50
     736816.50
     736847.50
     736877.50
     736908.50
     736939.50
     736969.50
     737000.50
     737030.50

datestr

Those are date numbers, and they don't make much sense to us humans. But already we can see something interesting: The datenums are not integers - they each end in .5, meaning the times correspond to noon on each day. To understand what these datenums mean, simply put them into the datestr function:

datestr(t)
ans =
  12×20 char array
    '01-Jan-2017 12:00:00'
    '01-Feb-2017 12:00:00'
    '01-Mar-2017 12:00:00'
    '01-Apr-2017 12:00:00'
    '01-May-2017 12:00:00'
    '01-Jun-2017 12:00:00'
    '01-Jul-2017 12:00:00'
    '01-Aug-2017 12:00:00'
    '01-Sep-2017 12:00:00'
    '01-Oct-2017 12:00:00'
    '01-Nov-2017 12:00:00'
    '01-Dec-2017 12:00:00'

That tells us exactly what we expected: This monthly data corresponds to noon on the first day of each month in 2017.

datevec

Another useful format is called datevec. Date vectors can be very helpful, especially when you want to analyze only the data, say, associated with the month of September. Date vectors give you the year, month, and day (and hour, minute, and second, if you wish) associated with any given times t. Here's how to get date vectors from a datnum array:

[year, month, day] = datevec(t);

With that, we now know the year, month, and day of each time t. Here they are, displayed all together:

[year month day]
ans =
       2017.00          1.00          1.00
       2017.00          2.00          1.00
       2017.00          3.00          1.00
       2017.00          4.00          1.00
       2017.00          5.00          1.00
       2017.00          6.00          1.00
       2017.00          7.00          1.00
       2017.00          8.00          1.00
       2017.00          9.00          1.00
       2017.00         10.00          1.00
       2017.00         11.00          1.00
       2017.00         12.00          1.00

The reason this is useful, is it's now very easy to get all the indices of dates corresponding to a given month. For example, here are all the indices corresponding to any September data:

ind = month==9
ind =
  12×1 logical array
   0
   0
   0
   0
   0
   0
   0
   0
   1
   0
   0
   0

datetime

If you'd like to convert datenum to datetime format, simply put t into the datetime function, and tell it you want to convert from datenum:

t = datetime(t,'ConvertFrom','datenum')
t = 
  12×1 datetime array
   01-Jan-2017 12:00:00
   01-Feb-2017 12:00:00
   01-Mar-2017 12:00:00
   01-Apr-2017 12:00:00
   01-May-2017 12:00:00
   01-Jun-2017 12:00:00
   01-Jul-2017 12:00:00
   01-Aug-2017 12:00:00
   01-Sep-2017 12:00:00
   01-Oct-2017 12:00:00
   01-Nov-2017 12:00:00
   01-Dec-2017 12:00:00

Converting back to datenum is this easy:

t = datenum(t)
t =
     736696.50
     736727.50
     736755.50
     736786.50
     736816.50
     736847.50
     736877.50
     736908.50
     736939.50
     736969.50
     737000.50
     737030.50

Author Info

This tutorial was written by Chad A. Greene for the Climate Data Toolbox for Matlab, February 2019.