SVGGraph date and time options

« Return to SVGGraph page

Skip to:

Data with key values that are dates and/or times is quite common, but SVGGraph would not usually be expecting it. The graph below shows what happens when your data key is a string containing the full date and time of an event, in this case major earthquakes in 2001.

2001-01-01T06:572001-01-10T16:022001-01-26T03:162001-02-13T19:282001-02-23T07:232001-02-28T18:542001-04-12T10:472001-05-23T12:102001-06-03T02:412001-06-23T20:332001-07-17T15:062001-08-09T02:062001-10-12T15:022001-10-27T05:352001-11-14T09:262001-12-12T14:0202.557.510 No datetime options set

This is a scatter graph, with the date/time keys along the X axis and numeric values on the Y axis. I've rotated the axis text to make it readable.

At first glance it doesn't look like there is anything wrong with this graph, but the first three axis labels are all in January 2001, the next three are in February 2001, then the labels after that skip to April, May and June. The values have been spread out evenly across the graph, even though the period between the actual events varies. SVGGraph doesn't know that the key strings have a deeper meaning, so it has treated them as plain text.

The datetime_keys option

Enabling the datetime_keys option makes SVGGraph parse all the keys in the data, converting them to an integer datestamp value (the number of seconds since the start of 1970). For pie graphs and the other pie-like graphs it doesn't do much more with the converted key, but for graphs that have axes it switches to using a different class for calculating the axis measurements using dates and times:

2001-012001-022001-032001-042001-052001-062001-072001-082001-092001-102001-112001-122002-0101.534.567.59 Setting datetime_keys

The example above uses the same data and settings as the previous graph, but enables datetime_keys. The X axis now starts at January 2001 and ends at the start of January 2002, with divisions and labels each month. It might not be obvious from this graph but the distance between the axis divisions varies with the length of the month, so February takes up about 10% less width than January or December.

Specifying datetime_key_format

The conversion from string to date and time value was simple in this case because the keys were in a standard format which the PHP date_create function recognises. If your data is in a different format you can set the datetime_key_format option to a string that describes the layout of your keys. The date_create_from_format PHP manual page describes the function SVGGraph uses to perform the conversion, and lists all the fields available for use in your format string.

Date and time axis options

There are several options for configuring the axis that start to support date and time values when the datetime_keys option is enabled. The graph below limits the range of the graph to the first two weeks of 2001 by setting the axis_max_h option to “2001-01-14T00:00”.

2001-01-012001-01-022001-01-032001-01-042001-01-052001-01-062001-01-072001-01-082001-01-092001-01-102001-01-112001-01-122001-01-132001-01-1401.534.567.59 A two-week axis

The graph now starts at 00:00 on the 1st of January 2001 and ends at 00:00 on the 14th of January 2001. SVGGraph has chosen to divide the graph up into days, labelling the divisions appropriately. SVGGraph has an internal list of date and time formats to use, depending on the division size:

$formats = array(
  'second' => 'Y-m-d H:i:s',
  'minute' => 'Y-m-d H:i',
  'hour' => 'Y-m-d H:i',
  'day' => 'Y-m-d',
  'month' => 'Y-m',
  'year' => 'Y'
);

You can override the defaults by specifying your own format in the datetime_text_format option. This can either be an array containing the specific formats to override, or a string that will override all of them. The format is explained on the PHP date function page.

Here is the graph above using the datetime_text_format set to “j M\nY” (and the text rotation turned off):

1 Jan20012 Jan20013 Jan20014 Jan20015 Jan20016 Jan20017 Jan20018 Jan20019 Jan200110 Jan200111 Jan200112 Jan200113 Jan200114 Jan20010123456789 Setting the text format

Using date/time values to limit the range of the graph is supported by the axis_max_h and axis_min_h options on ordinary grid-based graphs, and the axis_max_v and axis_min_v options on horizontal graphs.

Weeks

Weeks are handled slightly differently by SVGGraph, treating them as blocks of seven days starting on any day. They don't appear in the list of formats above because they use the same label format as individual days.

The graph below shows what happens when I set the end of the axis to the 14th of February, with SVGGraph deciding it is best divided into weeks:

Mon 1 Jan2001Mon 8 Jan2001Mon 15 Jan2001Mon 22 Jan2001Mon 29 Jan2001Mon 5 Feb2001Mon 12 Feb2001Mon 19 Feb20010123456789 Week-long divisions

I've added the day of the week into the datetime_text_format here to make it clearer. The 14th of February would not provide a whole number of weeks, so the axis has been extended to the end of that week. The first day of January in 2001 was a Monday, and since SVGGraph uses Monday as the first day of its week, that remains the start of the axis.

If you want to start your weeks on a different day, you can pass the start day to the datetime_week_start option. In the next graph it has been set to “sunday” instead:

Sun 31 Dec2000Sun 7 Jan2001Sun 14 Jan2001Sun 21 Jan2001Sun 28 Jan2001Sun 4 Feb2001Sun 11 Feb2001Sun 18 Feb20010123456789 Weeks start on Sunday

The graph above now starts on the Sunday before the first value, the 31st of December 2000. The end of the axis has also shifted back by a day to the Sunday at the end of the week containing the 14th of February.

Divisions and subdivisions

The other axes let you choose the division and subdivision distances using plain numeric values, but that doesn't work very well when they could be in seconds, hours or even years apart. To make it easier, the date/time axis supports specifying the units for dividing the grid:

1 Jan20014 Jan20017 Jan200110 Jan200113 Jan200116 Jan200119 Jan200122 Jan200125 Jan200128 Jan200131 Jan20013 Feb20016 Feb20019 Feb200112 Feb200115 Feb20010123456789 Divisions 3 days, subdivisions 36 hours

In this example I have set the grid_division_h option to the string “3 days” and subdivision_h to “36 hours”. The units available are listed here:

$unit_sizes = [
  'second' => 1,
  'minute' => 60,
  'hour' => 3600,
  'day' => 86400,
  'month' => 2629800, // avg year / 12
  'year' => 31557600  // avg year = 365.25 days (ignoring leap centuries)
];

As you can probably guess from this, the values are converted to a number of seconds, since that is what SVGGraph uses for all date and time data internally. The units will work with or without the trailing 's', so “1 hour” and “60 minutes” should give you exactly the same result.

Note: you must use whole numbers for the division and subdivision invervals.

The options for settings the division and subdivision sizes are grid_division_h and subdivision_h for the ordinary vertical graphs, and grid_division_v and subdivision_v for the horizontal graphs.

More labelling options

The axis text is not the only place that the date and time keys appear - the standard tooltips also contain the key, which can be formatted using the tooltip_datetime_format option:

Midday5th Jan1 Jan8 Jan15 Jan22 Jan29 Jan5 Feb12 Feb19 Feb01234567898:00am onFeb 1st Formatted tooltips

Here I've set the tooltip_datetime_format to “j M Y\ng:ia”, splitting the date and time across two lines (the keys are then followed by a comma and value). Hover your cursor over a marker to see the tooltip. I've also added a guideline, a custom label and a rectangular shape (the pink area from 20th to 22nd January) to show that date/time values are supported in other places too. The code for them is shown below.

$settings['guideline'] = [
  '2001-01-05T12:00', "Midday\n5th Jan", 'x',
  'text_position' => 'bottom right', 'colour' => '#c00',
];

$settings['label'] = [
  'g2001-02-01T08:00', 'g0', "8:00am on\nFeb 1st", 'type' => 'bubble'
];

$settings['shape'] = [
  'rect',
  'x' => 'g2001-01-20T00:00', 'y' => 'gt',
  'width' => 25, 'height' => 'gh',
  'fill' => '#f00', 'opacity' => 0.2,
];

The guideline position is the date and time in a string by itself, while the label and shape start with the 'g' prefix to show that the values are grid references (guideline positions are always grid references). The width of the pink rectangle shape is given as a value in pixels because date and time units are not supported by the shape options yet.

Data labels

There is one more option that I couldn't demonstrate on a scatter graph, data_label_datetime_format. The data keys are not normally shown in the data labels on grid-based graphs, but only on the pie graph and its variants.

26 Jan 20013:16am13 Feb 20017:28pm1 Jan 20016:57am13 Jan 20015:33pm9 Jan 20014:49pm13 Feb 20012:22pm10 Jan 20014:02pm17 Feb 20018:25pm Formatted data labels

For the example above I have used the same format as for the tooltips in the previous example, so data_label_datetime_format is set to “j M Y\ng:ia”. This is the only place date/time data is used on a pie graph.

Really long and very short ranges

SVGGraph can cope with a reasonable range of values for dates and times, but if your data spans hundreds of years or only fractions of a second then you are probably better off not using the date/time functions at all, but adjusting some of the standard axis options instead.

The callback functions provide the ability to alter the text for labels however you want, or the units_* options allow for setting the units on each axis - so you could label your X axis in microseconds by setting units_x to “μs”.

Other date and time systems

No. Seriously, the date and time system to which I am accustomed is complicated enough, and I'm not even going to worry about year 0 (there shouldn't be one) or the dates before (or maybe during) the calendar change from Julian to Gregorian. I haven't tested them, but it wouldn't surprise me if they didn't work. Contact me if you find that they don't work but you would really like them to, and I'll look into it.

« Back to top of page Titles and axis labels »