## Date/Time Plotting

Dates and times are among the many types of information that numerical data can represent. IDL provides a number of routines that offer specialized support for generating, analyzing, and displaying date- and time- based data (herein referred to as date/time data).

#### Julian Dates and Times

Within IDL, dates and times are typically stored as Julian dates. A Julian date is defined to be the number of days elapsed since noon on January 1, 4713 BCE. Following the astronomical convention, a Julian day is defined to start at 12pm (noon). The following table shows a few examples of calendar dates and their corresponding Julian dates.

Calendar Date
Julian Date
January 1, 4713 B.C.E., at 12pm
0
January 2, 4713 B.C.E., at 12pm
1
January 1, 2000 at 12pm
2451545

Julian dates can also include fractional portions of a day, thereby incorporating hours, minutes, and seconds. If the day fraction is included in a Julian date, it is represented as a double-precision floating point value. The day fraction is computed as follows:

One advantage of using Julian dates to represent dates and times is that a given date/time can be stored within a single variable (rather than storing the year, month, day, hour, minute, and second information in six different variables). Because each Julian date is simply a number, IDL's numerical routines can be applied to Julian dates just as for any other type of number.

 Note
Julian values must be in the range -1095 to 1827933925, which corresponds to calendar dates 1 Jan 4716 B.C.E. and 31 Dec 5000000, respectively.

#### Precision of Date/Time Data

The precision of any numerical value is defined as the smallest possible number that can be added to that value that produces a new value different from the first. Precision is typically limited by the data type of the variable used to store the number and the magnitude of the number itself. Within IDL, the following guide should be used when choosing a data format for date/time data:

• Time values that require a high precision, and that span a range of a few days or less, should be stored as double-precision values in units of "time elapsed" since the starting time, rather than in Julian date format. An example would be the "seconds elapsed" since the beginning of an experiment. In this case, the data can be treated within IDL as standard numeric data without the need to utilize IDL's specialized date/time features.
• Date values that do not include the time of day may be stored as long-integer Julian dates. The Julian date format has the advantage of being compact (one value per date) and being evenly spaced in days. As an example, January 1st for the years 2000, 2001, and 2002 can be stored as Julian days 2451545, 2451911, and 2452276. The precision of this format is 1 day.
• Date values where it is necessary to include the time of day can be stored as double-precision Julian dates, with the time included as a day fraction. Because of the large magnitude of the Julian date (such as Julian day 2451545 for 1 January 2000), the precision of most Julian dates is limited to 1 millisecond (0.001 seconds).

To determine the precision of a Julian date/time value, you can use the IDL MACHAR function:

```; Set date to January 1, 2000, at 12:15pm:
julian = JULDAY(1,1,2000,12,15,0)

; Get machine characteristics:
machine = MACHAR(/DOUBLE)

; Multiply by floating-point precision:
precision = julian*machine.eps

; Convert to seconds:
PRINT, precision*86400d0
```

### How to Generate Date/Time Data

The TIMEGEN function returns an array of double precision floating point values that represent date/time in terms of Julian dates. The first value of the returned array corresponds to a start date/time, and each subsequent value corresponds to the start date/time plus that array element's one-dimensional subscript multiplied by a step size for a given date/time unit. Unlike the other array generation routines in IDL, TIMEGEN includes a START keyword, which is necessary if the starting date/time is originally provided in calendar (month, day, year) form.

The following example begins with a start date of March 1, 2000 and increments every month for a full year:

```date_time = TIMEGEN(12, UNIT = 'Months', \$
START = JULDAY(3, 1, 2000))
```

where the UNIT keyword is set to 'Months' to increment by month and the START keyword is set to the Julian date form of March 1, 2000.

The results of the above call to TIMEGEN can be output using either of the following methods:

1. Using the CALDAT routine to convert the Julian dates to calendar dates:
2. ```CALDAT, date_time, month, day, year
FOR i = 0, (N_ELEMENTS(date_time) - 1) DO PRINT, \$
month[i], day[i], year[i], \$
FORMAT = '(i2.2, "/", i2.2, "/", i4)'
```
3. Using the calendar format codes:
4. ```PRINT, date_time, format = '(C(CMOI2.2, "/", CDI2.2, "/", CYI))'
```

The resulting calendar dates are printed out as follows:

```03/01/2000
04/01/2000
05/01/2000
06/01/2000
07/01/2000
08/01/2000
09/01/2000
10/01/2000
11/01/2000
12/01/2000
01/01/2001
02/01/2001
```

The TIMEGEN routine contains several keywords to provide specific date/time data generation. For more information, see the TIMEGEN.

### Displaying Date/Time Data on an Axis in Direct Graphics

You can display date/time data on plots, contours, and surfaces through the tick settings of the date/time axis. Date/time data can be displayed on any axis (x, y or z). The date/time data is stored as Julian dates, but the LABEL_DATE routine and axis keywords allow you to display this data as calendar dates. The following examples show how to display one-dimensional and two-dimensional date/time data.

#### Displaying Date/Time Data on a Plot Display

Date/time data usually comes from measuring data values at specific times. For example, the displacement (in inches) of an object might be recorded at every second for 37 seconds after the initial recording of 59 minutes and 30 seconds after 2 o'clock pm (14 hundred hours) on the 30th day of March in the year 2000 as follows

```number_samples = 37
date_time = TIMEGEN(number_samples, UNITS = 'Seconds', \$
START = JULDAY(3, 30, 2000, 14, 59, 30))
displacement = SIN(10.*!DTOR*FINDGEN(number_samples))
```

Normally, this type of data would be imported into IDL from a data file. However, this section is designed specifically to show how to display date/time data, not how to import data from a file; therefore, the data for this example is created with the above IDL commands.

Before displaying this one-dimensional data with the PLOT routine, the format of the date/time values is specified through the LABEL_DATE routine as follows

```date_label = LABEL_DATE(DATE_FORMAT = ['%I:%S'])
```

where %I represents minutes and %S represents seconds.

The resulting format is specified in the call to the PLOT routine with the XTICKFORMAT keyword:

```PLOT, date_time, displacement, /XSTYLE, \$
; displaying titles.
TITLE = 'Measured Signal', \$
XTITLE = 'Time (seconds)', \$
YTITLE = 'Displacement (inches)', \$
; applying date/time formats to X-axis labels.
XTICKFORMAT = 'LABEL_DATE', \$
XTICKUNITS = 'Time', \$
XTICKINTERVAL = 5
```

The XTICKUNITS keyword is set to note the tick labels contain date/time data. The XTICKINTERVAL keyword is set to place the major tick marks at every five second interval. These keyword settings produce the following results:

The above display shows the progression of the date/time variable, but it does not include all of the date/time data we generated with the TIMEGEN routine. This data also includes hour, month, day, and year information. IDL can display this information with additional levels to the date/time axis. You can control the number of levels to draw and the units used at each level with the XTICKUNITS keyword. You can specify the formatting for these levels by changing the DATE_FORMAT keyword setting to the LABEL_DATE routine:

```date_label = LABEL_DATE(DATE_FORMAT = \$
['%I:%S', '%H', '%D %M, %Y'])
```

where %H represents hours, %D represents days, %M represents months, and %Y represents years. Notice DATE_FORMAT is specified with a three element vector. Date/time data can be displayed on an axis with three levels. The format of these levels are specified through this vector.

In this example, the first level (closest to the axis) will contain minute and second values separated by a colon (%I:%S). The second level (just below the first level) will contain the hour values (%H). The third level (the final level farthest from the axis) will contain the day and month values separated by a space and year value separated from the day and month values by a comma (%D %M, %Y). For more information, see the description of the LABEL_DATE routine.

Besides the above change to the LABEL_DATE routine, you must also change the settings of the keywords to the PLOT routine to specify a multiple level axis:

```PLOT, date_time, displacement, /XSTYLE, \$
; displaying titles.
TITLE = 'Measured Signal', \$
XTITLE = 'Time (seconds)', \$
YTITLE = 'Displacement (inches)', \$
; applying date/time formats to X-axis labels.
POSITION = [0.2, 0.25, 0.9, 0.9], \$
XTICKFORMAT = ['LABEL_DATE', 'LABEL_DATE', 'LABEL_DATE'], \$
XTICKUNITS = ['Time', 'Hour', 'Day'], \$
XTICKINTERVAL = 5
```

The POSITION keyword is set to allow the resulting display to contain all three levels and the title of the date/time axis. The XTICKFORMAT is now set to a string array containing an element for each level of the axis. The XTICKUNITS keyword is set to note the unit of each level. These keyword settings produce the results shown in the following figure.

Notice the three levels of the X-axis. These levels are arranged as specified by the previous call to the LABEL_DATE routine.

### Displaying Date/Time Data on a Contour Display

Another possible example may be the surface temperature (in degrees Celsius) of each degree of a single circle on a sphere recorded at every second for 37 seconds after the initial recording of 59 minutes and 30 seconds after 2 o'clock pm (14 hundred hours) on the 30th day of March in the year 2000:

```number_samples = 37
date_time = TIMEGEN(number_samples, UNITS = 'Seconds', \$
START = JULDAY(3, 30, 2000, 14, 59, 30))
angle = 10.*FINDGEN(number_samples)
temperature = BYTSCL(SIN(10.*!DTOR* \$
FINDGEN(number_samples)) # COS (!DTOR*angle))
```

Since the final contour display will be filled, we should define a color table:

```DEVICE, DECOMPOSED = 0
```

The call to the DEVICE command with the DECOMPOSED keyword set to zero allows color tables to be used on TrueColor displays, which may be the default setting on some systems. The call to the LOADCT routine loads the Standard Gamma-II (number 5) color table, which is a part of IDL's libraries.

As with the one-dimensional case, the format of the date/time values is specified through the LABEL_DATE routine as follows

```date_label = LABEL_DATE(DATE_FORMAT = \$
['%I:%S', '%H', '%D %M, %Y'])
```

where %I represents minutes, %S represents seconds, %H represents hours, %D represents days, %M represents months, and %Y represents years.

The first level (closest to the axis) will contain minute and second values separated by a colon (%I:%S). The second level (just below the first level) will contain the hour values(%H). The third level (the final level farthest from the axis) will contain the day and month values separated by a space and year value separated from the day and month values by a comma (%D %M, %Y).

The resulting format is specified by using the CONTOUR routine with the XTICKFORMAT keyword:

```CONTOUR, temperature, angle, date_time, \$
; specifying contour levels and fill colors.
LEVELS = BYTSCL(INDGEN(8)), /XSTYLE, /YSTYLE, \$
C_COLORS = BYTSCL(INDGEN(8)), /FILL, \$
; displaying titles.
TITLE = 'Measured Temperature (degrees Celsius)', \$
XTITLE = 'Angle (degrees)', \$
YTITLE = 'Time (seconds)', \$
; applying date/time formats to X-axis labels.
POSITION = [0.25, 0.2, 0.9, 0.9], \$
YTICKFORMAT = ['LABEL_DATE', 'LABEL_DATE', 'LABEL_DATE'], \$
YTICKUNITS = ['Time', 'Hour', 'Day'], \$
YTICKINTERVAL = 5, \$
YTICKLAYOUT = 2
; Applying contour lines over the original contour display.
CONTOUR, temperature, angle, date_time, /OVERPLOT, \$
LEVELS = BYTSCL(INDGEN(8))
```

As in the plot example, the POSITION keyword is set to allow the resulting display to contain all three levels and the title of the date/time axis. The YTICKUNITS keyword is set to note the unit of each level. And the YTICKINTERVAL keyword is set to place the major tick marks at every five second interval.

This example also contains the YTICKLAYOUT keyword. By default, this keyword is set to 0, which provides the date/time layout shown in the plot example.

In this example, YTICKLAYOUT is set to 2, which rotates and boxes the tick labels to provide the following results:

### Using System Variables to Display Date/Time Data

The settings we used to display our date/time data could have been specified through system variables instead of keywords. The following table shows the relationship between these keywords and their system variables:

Keywords
System Variables
[XYZ]TICKUNITS
![XYZ].TICKUNITS
[XYZ]TICKINTERVAL
![XYZ].TICKINTERVAL
[XYZ]TICKLAYOUT
![XYZ].TICKLAYOUT

Usually, keywords are used more frequently than system variables, but system variables are better when trying to establish a consistent display style. For example, we could have established a date/time axis style with these system variables before producing our previous displays:

```; Establishing an axis style.

!X.TICKFORMAT = ['LABEL_DATE', 'LABEL_DATE', 'LABEL_DATE']

!X.TICKUNITS = ['Time', 'Hour', 'Day']

!X.TICKINTERVAL = 5

!X.TICKLAYOUT = 2
; Displaying data.
PLOT, date_time, displacement, /XSTYLE, \$
TITLE = 'Measured Signal', \$
XTITLE = 'Time (seconds)', \$
YTITLE = 'Displacement (inches)', \$
POSITION = [0.2, 0.7, 0.9, 0.9]
CONTOUR, temperature, date_time, angle, /FILL, \$
LEVELS = BYTSCL(INDGEN(8)), /XSTYLE, /YSTYLE, \$
C_COLORS = BYTSCL(INDGEN(8)), /NOERASE, \$
TITLE = 'Measured Temperature (degrees Celsius)', \$
XTITLE = 'Angle (degrees)', \$
YTITLE = 'Time (seconds)', \$
POSITION = [0.2, 0.25, 0.9, 0.45]
CONTOUR, temperature, date_time, angle, /OVERPLOT, \$
LEVELS = BYTSCL(INDGEN(8))

!X.TICKLAYOUT = 0

!X.TICKINTERVAL = 0

!X.TICKUNITS = ''

!X.TICKFORMAT = ''
```

Notice these system variables are set to their default values after the two displays are shown. When using system variables instead of keywords, remember to reset the system variables back to their default values. The above example produces the following results.