SVGGraph date and time options
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.
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
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:
The example above uses the same data and settings as the previous graph, but
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.
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
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”.
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
date function page.
Here is the graph above using the
datetime_text_format set to
“j M\nY” (and the text rotation turned off):
Using date/time values to limit the range of the graph is supported by the
axis_min_h options on ordinary
grid-based graphs, and the
options on horizontal graphs.
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:
I've added the day of the week into the
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:
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 axis types 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:
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
subdivision_h for the ordinary
vertical graphs, and
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
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.
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
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
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
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.