{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-| Module : Graphics.Vega.VegaLite.Time Copyright : (c) Douglas Burke, 2018-2021 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 , dateTimeSpec , timeUnitSpec ) where import qualified Data.Text as T import Data.Aeson ((.=), object, toJSON) import Data.Aeson.Types (Pair) #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 (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 . 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 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 -> Pair 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 dateTimeSpec :: [DateTime] -> VLSpec dateTimeSpec = object . map dateTimeProperty 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]