Dates and Time Conventions

Throughout the EDSS and Models-3 systems -- and particularly in the I/O API -- dates and times represent Greenwich Mean Time. Dates and times (and time-increments) are stored as integers, using the coding formats
    HHMMSS  = 10000 * hour  +  100 * minutes  +  seconds
    YYYYDDD =  1000 * year  +  day
where the year is 4-digits (1994, say, rather than just 94), and the day is the Julian day-number (1,...,365 or 366).

Note that time intervals coded HHMMSS will suffer INTEGER-overflow after a little more than 24.5 years; however, for I/O API-3.1 or later, a number of I/O API routines—CURREC(), CURRSTEP(), JSTEP3(), LASTTIME(), NEXTTIME()—are carefully coded so as to avoid such overflow, and can be used for time periods as long as several thousand years. For I/O API files, the limiting factor is INTEGER-overflow for the number of records. (For files with a one-hour timestep, for example, this limits file-duration to 89,478 years (which is sufficient for most applications:-).)

A time step sequence is a sequence of dates and times

    { [date(0),time(0)], [date(1),time(1)], ... [date[N],time[N] }
having a starting date and time [date(0),time(0)], a time increment dT, and such that each [date(K),time(K)] is exactly dT away from [date(K-1),time(K-1)]—for example, the following is a five-step time step sequence starting at midnight January 2, 1980, with time step three hours:
    { 1980002:000000, 1980002:030000, 1980002:060000, 1980002:090000, 1980002:120000 }
Note that each file has a time step sequence (where by convention, time increment dT=0 means that the data in the file is time-independent, and routines like READ3() and WRITE3() which deal with time-independent files ignore the date-and-time arguments. Note that programs (e.g., m3tools programs) which control their run timestep-sequence by specification of starting date&time, timestep, and ending date&time are in practice not subject to INTEGER-overflow problems; however, older ones controlled by starting date&time, timestep, and duration may well be subject to the above-mentioned 24.5-year limit. Unfortunately, this requires an incompatible interface-change to fix...

Standard-Year and Standard-Week files are files for climatological and similar year-independent data. For these files, INTERP3() and possibly WKDAY() can be used to extract data for dates and times for the relevant day of year 0 according to the patterns

    ...
    !!  Standard-Year data:
    !!  Note:  Fortran MOD() doesn't work "right"
    !!  for negative numbers:

    IF ( JDATE .GT. 0 ) THEN
        DAY = MOD( JDATE, 1000 )
    ELSE
        YEAR = (-JDATE)/1000 + 1
        DAY  = MOD( JDATE + 1000*YEAR, 1000 )
    END IF
    IF ( .NOT.INTERP3(<file>, <variable>, DAY, JTIME, ... )
    ...
    !!  Standard-Week data:

    DAY = WKDAY( JDATE )
    IF ( .NOT.INTERP3(<file>, <variable>, DAY, JTIME, ... )
    ...
Standard-year files should cover a period at least from Year 1:Day 1 and at least through Year 1:Day 366, and standard-week files should cover a period at least from Year 1:Day 1 and at least through Year 1:Day 8. Note that for monthly data valid at the middle of the month, the starting date should be something like Year (-1), Day 351, the time step 30.5 days (732 hours), and the ending date Year 1, Day 16.

There are a number of utility routines available for manipulating dates and times, in addition to programs gregdate and juldate for converting back and forth between model-convention Julian dates and ordinary calendar dates. Note that for these utility routines, time increments may perfectly well be negative -- just make sure you keep the parts all positive or all negative; a time increment of -33000 means to step three and a half hours into the past, for example; the hours part is -3, the minutes part is -30, and the seconds part is 0. This way of representing dates and times is easy to understand and manipulate when you are watching code in the debugger (you don't have to turn the UNIXism "seconds since Jan. 1, 1970" into something meaningful for your model run, nor do you have to remember whether April has 30 days or 31 when your model run crosses over from April to May).

Utility routines for manipulating dates and times are the following:

CURRSTEP: find start of <timestep> containing <time>
DAYMON: find month and day-of-month for <jdate>
DT2STR: Construct string for <jdate> and <time>
GETDTTIME: DATETIME.html get current wall-clock date and time
HHMMSS: construct string "HHMMSS" for <time>
ISDSTIME: Is Daylight Savings Time in effect for the indicated date?
JSTEP3: find record number (Fortran-style 1,2,3,...) for <jdate:jtime> within the time step sequence <sdate:stime:tstep> (or return -1 if not on the sequence.
JULIAN: find Julian day number for <month > <day> &lt;year>
MMDDYY: construct string "Month DD, YYYY" for <jdate>
NEXTIME: update <jdate>, <time> by <timestep>
SEC2TIME: get Models-3 time representation for <seconds>
SECSDIFF: find time diff between two <jdate-time>s
TIME2SEC: get number of seconds for <time>
WKDAY: get day-of-week (1...7) for <jdate>

Programs for manipulating dates and times are the following:

datshift: Take calendar date (form YYYYMMDD) and a number of days D, and report the date D days later.
gregdate: compute Gregorian calendar style date, day-of-week, and whether or not daylight savings time is in effect from input Julian-form date
juldate: compute Julian date day-of-week, and whether or not daylight savings time is in effect from input Gregporian-form date
greg2jul: Convert Gregorian-style dates to Julian-style and echo the result (e.g., for use in scripting).
jul2greg: Convert Julian-style dates to Gregorian-style and echo the result (e.g., for use in scripting).
juldiff: Compute the number of days between two Julian dates and echo the result (e.g., for use in scripting).
julshift: Shift a Julian date by a specified number of days and echo the result (e.g., for use in scripting).


Previous Section: Grids and Coordinate Systems

Next Section: Calling from Fortran

Up: Conventions

To: Models-3/EDSS I/O API: The Help Pages