hvega-0.10.0.0: src/Graphics/Vega/VegaLite/Time.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Graphics.Vega.VegaLite.Time
Copyright : (c) Douglas Burke, 2018-2020
License : BSD3
Maintainer : dburke.gw@gmail.com
Stability : unstable
Portability : OverloadedStrings
Time-related types.
-}
module Graphics.Vega.VegaLite.Time
( DateTime(..)
, MonthName(..)
, DayName(..)
, TimeUnit(..)
, BaseTimeUnit(..)
-- not for external export
, dateTimeProperty
, timeUnitSpec
) where
import qualified Data.Text as T
import Data.Aeson ((.=), object, toJSON)
#if !(MIN_VERSION_base(4, 12, 0))
import Data.Monoid ((<>))
#endif
-- added in base 4.8.0.0 / ghc 7.10.1
import Numeric.Natural (Natural)
import Graphics.Vega.VegaLite.Specification (LabelledSpec, VLSpec)
{-|
Allows a date or time to be represented. This is typically part of a list of
@DateTime@ items to provide a specific point in time. For details see the
<https://vega.github.io/vega-lite/docs/types.html#datetime Vega-Lite documentation>.
There is __no check__ that the provided @Int@ values lie within the
required bounds.
A 'DateTime' value of 'DTDay' or 'DTDayNum' should not be combined with
'DTYear', 'DTQuarter', 'DTMonth', 'DTMonthNum', or 'DTDate'.
-}
data DateTime
= DTYear Int
| DTQuarter Int
-- ^ The quarter of the year (1 to 4, inclusive).
| DTMonth MonthName
| DTMonthNum Int
-- ^ The month number (1 to 12, inclusive).
--
-- @since 0.5.0.0
| DTWeek Int
-- ^ The week number. Each week begins on Sunday, which means that days
-- before the first Sunday of the year are considered to be in week 0,
-- as the first Sunday of the year is the start of week 1.
--
-- @since 0.10.0.0
| DTDay DayName
| DTDayNum Int
-- ^ The day number (1 represents Monday, 7 is Sunday).
--
-- @since 0.5.0.0
| DTDayOfYear Int
-- ^ The day of the year (1 to 366).
--
-- @since 0.10.0.0
| DTDate Int
-- ^ Day of the month (1 to 31, inclusive).
| DTHours Int
-- ^ Hour of the day, where 0 is midnight, 1 is 1am, and
-- 23 is 11pm.
| DTMinutes Int
-- ^ The minute of an hour (0 to 59, inclusive).
| DTSeconds Int
-- ^ The second of a minute (0 to 59, inclusive).
| DTMilliseconds Int
-- ^ The milliseconds of a second (0 to 999, inclusive).
-- | Identifies the day of the week.
data DayName
= Mon
| Tue
| Wed
| Thu
| Fri
| Sat
| Sun
-- | Identifies a month of the year.
data MonthName
= Jan
| Feb
| Mar
| Apr
| May
| Jun
| Jul
| Aug
| Sep
| Oct
| Nov
| Dec
-- Vega-Lite 4.4.0 has
-- LocalMultiTimeUnit which is yearquarter, yearquartermonth, ,secondsmilliseconds
-- LocalSingleTimeUnit year, quarter, ..., milliseconds
-- and
-- UtcMultiTimeUnit which is utc <> LocalMultiTimeUnit
-- UtcSingleTimeUnit utc <> LocalSingleTimeUnit
--
-- TimeUnit is either of SingleTimeUnit or MultiTimeUnit
-- SingleTimeUnut is either of LocalSingleTimeUnit or UtcSingleTimeUnit
-- MultiTimeUnit is either of LocalMultiTieUnit or UtcMultiTimeUnit
--
-- "timeUnit" settings are TimeUnit or TimeUnitParams
--
-- TimeUnitParams is an object with fields
-- maxbins - number
-- step - number
-- unit - this is TimeUnit
-- utc - boolean
--
{-|
Describes a unit of time. Useful for encoding and transformations. See the
<https://vega.github.io/vega-lite/docs/timeunit.html Vega-Lite documentation>
for further details.
@
'Graphics.Vega.VegaLite.encoding'
. 'Graphics.Vega.VegaLite.position' 'Graphics.Vega.VegaLite.X' [ 'Graphics.Vega.VegaLite.PName' "date", 'Graphics.Vega.VegaLite.PmType' 'Graphics.Vega.VegaLite.Temporal', 'Graphics.Vega.VegaLite.PTimeUnit' ('Utc' 'YearMonthDateHours') ]
@
Prior to version @0.10.0.0@ the field was a combination of what is now
'BaseTimeUnit' and the \"option\" fields (e.g. encode as UTC or the
maximum nuber of bins).
-}
data TimeUnit
= TU BaseTimeUnit
-- ^ Encode a time as local time.
| Utc BaseTimeUnit
-- ^ Encode a time as UTC (coordinated universal time, independent of local time
-- zones or daylight saving).
| TUMaxBins Natural
-- ^ The maximum number of bins to use when discretising time values.
-- This can be useful as an algternative to explicitly providing the
-- time unit to bin by, as it will be inferred from the temporal
-- extent and the number of bins. As an example, @[TUMaxBins 366]@
-- will bin by day when applied to a dataset of hourly readings
-- for a full year.
--
-- @since 0.6.0.0
| TUStep Double BaseTimeUnit
-- ^ The number of steps between time-unit bins, in terms of the
-- least-significant unit provided. So @TUStep 14 YearMonthDate@
-- will bin temporal data into bi-weekly groups.
--
-- @since 0.6.0.0
| UtcStep Double BaseTimeUnit
-- ^ The number of steps between time-unit bins, in terms of the
-- least-significant unit provided for UTC times.
-- So @UtcStep 14 YearMonthDate]@
-- will bin temporal data into bi-weekly groups.
--
-- @since 0.10.0.0
{-|
Define the time unit, either as a base unit - such as 'Hours' - or
as a composite type, for example 'WeeksDayHours'.
@since 0.10.0.0
-}
data BaseTimeUnit
= Year
-- ^ Year.
| Quarter
-- ^ Quarter of the year.
| Month
-- ^ Month of the year.
| Week
-- ^ Sunday-based week number. Days before the first Sunday of the year
-- are considered to be in week 0, and the first Sunday of the year
-- is the start of week 1,
--
-- @since 0.10.0.0
| Date
-- ^ Day of the month (1 to 31).
| Day
-- ^ Day of the week.
| DayOfYear
-- ^ Day of the year (starting at 1).
--
-- @since 0.10.0.0
| Hours
-- ^ Hour of the day.
| Minutes
-- ^ Minutes of the hour.
| Seconds
-- ^ Seconds of the minute.
| Milliseconds
-- ^ Milliseconds.
| YearQuarter
-- ^ Year and quarter.
| YearQuarterMonth
-- ^ Year, quarter, and month.
| YearMonth
-- ^ Year and month.
| YearMonthDate
-- ^ Year, month, and day of month.
| YearMonthDateHours
-- ^ Year, month, day of month, and hour of day.
| YearMonthDateHoursMinutes
-- ^ Year, month, day of month, hour of day, and minutes.
| YearMonthDateHoursMinutesSeconds
-- ^ Year, month, day of month, hour of day, minutes, and seconds.
| YearWeek
-- ^ Year and week.
--
-- @since 0.10.0
| YearWeekDay
-- ^ Year, week, and day.
--
-- @since 0.10.0
| YearWeekDayHours
-- ^ Year, week, day, and hour of day.
--
-- @since 0.10.0
| YearWeekDayHoursMinutes
-- ^ Year, week, day, hour of day, and minutes.
--
-- @since 0.10.0
| YearWeekDayHoursMinutesSeconds
-- ^ Year, week, day, hour of day, minutes, and seconds.
--
-- @since 0.10.0
| YearDayOfYear
-- ^ Year and day of year.
--
-- @since 0.10.0
| QuarterMonth
-- ^ Quarter of the year and month.
| MonthDate
-- ^ Month of the year and day of the month.
| MonthDateHours
-- ^ Month, day of the month, and hours.
--
-- @since 0.10.0.0
| MonthDateHoursMinutes
-- ^ Month, day of the month, hours, and minutes.
--
-- @since 0.10.0.0
| MonthDateHoursMinutesSeconds
-- ^ Month, day of the month, hours, minutes, and seconds.
--
-- @since 0.10.0.0
| WeekDay
-- ^ Week and day of month.
--
-- @since 0.10.0.0
| WeeksDayHours
-- ^ Week, day of month, and hours.
--
-- @since 0.10.0.0
| WeeksDayHoursMinutes
-- ^ Week, day of month, hours, and minutes.
--
-- @since 0.10.0.0
| WeeksDayHoursMinutesSeconds
-- ^ Week, day of month, hours, minutes, and seconds.
--
-- @since 0.10.0.0
| DayHours
-- ^ Day of the week and hours.
--
-- @since 0.10.0.0
| DayHoursMinutes
-- ^ Day of the week, hours, and minutes.
--
-- @since 0.10.0.0
| DayHoursMinutesSeconds
-- ^ Day of the week, hours, minutes, and seconds.
--
-- @since 0.10.0.0
| HoursMinutes
-- ^ Hour of the day and minutes.
| HoursMinutesSeconds
-- ^ Hour of the day, minutes, and seconds.
| MinutesSeconds
-- ^ Minutes of the hour and seconds.
| SecondsMilliseconds
-- ^ Seconds of the minute and milliseconds.
baseTimeUnitLabel :: BaseTimeUnit -> T.Text
baseTimeUnitLabel Year = "year"
baseTimeUnitLabel Quarter = "quarter"
baseTimeUnitLabel Month = "month"
baseTimeUnitLabel Week = "week"
baseTimeUnitLabel Date = "date"
baseTimeUnitLabel Day = "day"
baseTimeUnitLabel DayOfYear = "dayofyear"
baseTimeUnitLabel Hours = "hours"
baseTimeUnitLabel Minutes = "minutes"
baseTimeUnitLabel Seconds = "seconds"
baseTimeUnitLabel Milliseconds = "milliseconds"
baseTimeUnitLabel YearQuarter = "yearquarter"
baseTimeUnitLabel YearQuarterMonth = "yearquartermonth"
baseTimeUnitLabel YearMonth = "yearmonth"
baseTimeUnitLabel YearMonthDate = "yearmonthdate"
baseTimeUnitLabel YearMonthDateHours = "yearmonthdatehours"
baseTimeUnitLabel YearMonthDateHoursMinutes = "yearmonthdatehoursminutes"
baseTimeUnitLabel YearMonthDateHoursMinutesSeconds = "yearmonthdatehoursminutesseconds"
baseTimeUnitLabel YearWeek = "yearweek"
baseTimeUnitLabel YearWeekDay = "yearweekday"
baseTimeUnitLabel YearWeekDayHours = "yearweekdayhours"
baseTimeUnitLabel YearWeekDayHoursMinutes = "yearweekdayhoursminutes"
baseTimeUnitLabel YearWeekDayHoursMinutesSeconds = "yearweekdayhoursminutesseconds"
baseTimeUnitLabel YearDayOfYear = "yeardayofyear"
baseTimeUnitLabel QuarterMonth = "quartermonth"
baseTimeUnitLabel MonthDate = "monthdate"
baseTimeUnitLabel MonthDateHours = "monthdatehours"
baseTimeUnitLabel MonthDateHoursMinutes = "monthdatehoursminutes"
baseTimeUnitLabel MonthDateHoursMinutesSeconds = "monthdatehoursminutesseconds"
baseTimeUnitLabel WeekDay = "weekday"
baseTimeUnitLabel WeeksDayHours = "weeksdayhours"
baseTimeUnitLabel WeeksDayHoursMinutes = "weeksdayhoursminutes"
baseTimeUnitLabel WeeksDayHoursMinutesSeconds = "weeksdayhoursminutesseconds"
baseTimeUnitLabel DayHours = "dayhours"
baseTimeUnitLabel DayHoursMinutes = "dayhoursminutes"
baseTimeUnitLabel DayHoursMinutesSeconds = "dayhoursminutesseconds"
baseTimeUnitLabel HoursMinutes = "hoursminutes"
baseTimeUnitLabel HoursMinutesSeconds = "hoursminutesseconds"
baseTimeUnitLabel MinutesSeconds = "minutesseconds"
baseTimeUnitLabel SecondsMilliseconds = "secondsmilliseconds"
dateTimeProperty :: DateTime -> LabelledSpec
dateTimeProperty (DTYear y) = "year" .= y
dateTimeProperty (DTQuarter q) = "quarter" .= q
dateTimeProperty (DTMonth mon) = "month" .= monthNameLabel mon
dateTimeProperty (DTMonthNum n) = "month" .= n
dateTimeProperty (DTWeek w) = "week" .= w
dateTimeProperty (DTDate dt) = "date" .= dt
dateTimeProperty (DTDay day) = "day" .= dayLabel day
dateTimeProperty (DTDayOfYear n) = "dayofyear" .= n
dateTimeProperty (DTDayNum n) = "day" .= n
dateTimeProperty (DTHours h) = "hours" .= h
dateTimeProperty (DTMinutes m) = "minutes" .= m
dateTimeProperty (DTSeconds s) = "seconds" .= s
dateTimeProperty (DTMilliseconds ms) = "milliseconds" .= ms
dayLabel :: DayName -> T.Text
dayLabel Mon = "Mon"
dayLabel Tue = "Tue"
dayLabel Wed = "Wed"
dayLabel Thu = "Thu"
dayLabel Fri = "Fri"
dayLabel Sat = "Sat"
dayLabel Sun = "Sun"
monthNameLabel :: MonthName -> T.Text
monthNameLabel Jan = "Jan"
monthNameLabel Feb = "Feb"
monthNameLabel Mar = "Mar"
monthNameLabel Apr = "Apr"
monthNameLabel May = "May"
monthNameLabel Jun = "Jun"
monthNameLabel Jul = "Jul"
monthNameLabel Aug = "Aug"
monthNameLabel Sep = "Sep"
monthNameLabel Oct = "Oct"
monthNameLabel Nov = "Nov"
monthNameLabel Dec = "Dec"
fromT :: T.Text -> VLSpec
fromT = toJSON
timeUnitSpec :: TimeUnit -> VLSpec
timeUnitSpec (TU tu) = fromT (baseTimeUnitLabel tu)
timeUnitSpec (Utc tu) = fromT ("utc" <> baseTimeUnitLabel tu)
timeUnitSpec (TUStep x tu) = object ["step" .= x, "unit" .= baseTimeUnitLabel tu]
timeUnitSpec (UtcStep x tu) = object ["step" .= x, "unit" .= ("utc" <> baseTimeUnitLabel tu)]
timeUnitSpec (TUMaxBins n) = object ["maxbins" .= n]