Date and Time in Julia
Lets begin this week with a short talk about how to deal with Dates in Julia. So, first of all, import the Dates
module (it comes packaged with Julia, but isn’t in Base
):
using Dates
Now you have Date
and DateTime
dataypes to ease your work with chronological data. Both essentially work by manipulating integers, Date
gives you day-level precision, while DateTime
is precise to the millisecond.
Construction
There’s many provided constructors, but we shall be focusing on the most used ones in a usual use-case. Rest can be found here. The classic way of initializing are to simply pass in the date and/or time as integers as arguments in order:
julia> Date(2020,11,25)
2020-11-25
julia> DateTime(2020,11,25,11,30,55)
2020-11-25T11:30:55
If you supply less arguments, they assume the default value:
julia> Date(2020)
2020-01-01
julia> DateTime(2020,11,25)
2020-11-25T00:00:00
Or you can supply the arguments out of order, but pass in Dates
‘s children objects:
julia> Date(Dates.Month(11),Dates.Year(2020))
2020-11-01
julia> DateTime(Dates.Year(2020),Dates.Hour(13),Dates.Minute(5))
2020-01-01T13:05:00
Often, you want to parse dates from a string, you can do that by specifying the format its in:
julia> Date("2020-11-25","y-m-d")
2020-11-25
julia> Date("2020-25-11","y-d-m")
2020-11-25
julia> DateTime("2020-25-11-13","y-d-m-H")
2020-11-25T13:00:00
julia> DateTime("2020-11-13","y-m-H")
2020-11-01T13:00:00
It’s quite flexible, and lets you also use fixed-width formatting:
julia> DateTime("20201113","yyyymmdd")
2020-11-13T00:00:00
julia> DateTime("20201113","yyyymmHH")
2020-11-01T13:00:00
You can also save the formatting scheme, as a DateFormat
object:
julia> format="y-d-m"
"y-d-m"
julia> Date("2020-25-11",format)
2020-11-25
Accessing
For an existing object, you can read its various ‘fields’ using the familiar dot notation:
julia> now=Date("2020-20-10",format)
2020-10-20
julia> Dates.year(now)
2020
julia> Dates.day(now)
20
julia> Dates.week(now)
43
But you must be careful of which type you’re on here, for example, it makes no sense for a Date
object to have an hour field:
julia> Dates.hours(now)
ERROR: UndefVarError: hours not defined
Stacktrace:
[1] getproperty(::Module, ::Symbol) at ./Base.jl:26
[2] top-level scope at REPL[101]:1
julia> now=DateTime("2020-20-10",format)
2020-10-20T00:00:00
julia> Dates.hour(now)
0
You can also retrieve multiple fields in one go:
julia> Dates.yearmonth(now)
(2020, 10)
Accessing multiple fields this way also gives performance benefit, as opposed to individual retrieval.
Finally, as I mentioned earlier, Date
and DateTime
are essentially integers. You can have a look at that integer too:
julia> Dates.value(now)
63738835200000
Operations
You can compare the constructed objects, with later being related to greater:
julia> before=Date("200-20-10",format)
0200-10-20
julia> now>before
true
julia> now==before
false
Or, given two objects, you can find the duration that passed in between.
julia> now-before
664742 days
julia> before-now
-664742 days
But most importantly, you can do chronological arithmetic using Dates
‘ objects:
julia> now
2020-10-20T00:00:00
julia> now+Dates.Day(2)+Dates.Month(2) #Add 2 days and 2 months to the object now
2020-12-22T00:00:00
julia> now+Dates.Hour(4) # Add 4 hours the object now
2020-10-20T04:00:00
You can round off to a particular resolution, and have similar overloading of ceil
and floor
:
julia> round(Dates.Hour(3000),Dates.Day) #How many days in 3000 hours
125 days
julia> floor(Dates.Hour(3023),Dates.Day) #How many complete days in 3023 hours
125 days
julia> ceil(Dates.Hour(3023),Dates.Day) #How many new days started in 3023 hours
126 days
Convenience functions
Often, when dealing with chronological data, you want to know what day of the week it is
julia> Dates.dayofweek(now)
2
julia> Dates.dayname(now)
"Tuesday"
Or perhaps even, which occurrence of a day is it in that month
julia> Dates.dayofweekofmonth(now)
3
Of course there are the vanilla functions:
julia> Dates.monthname(now)
"October"
julia> Dates.isleapyear(now)
true
julia> Dates.dayofquarter(now)
20