From 2bd60160adaff922d1e89314b1ff207e28e3371e Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Fri, 3 Jul 2020 20:39:13 +0200 Subject: [PATCH] Add documentation page --- docs/Project.toml | 1 + docs/make.jl | 3 +- docs/src/dates.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 docs/src/dates.md diff --git a/docs/Project.toml b/docs/Project.toml index 7eb4fd3c..6128171d 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,5 @@ [deps] +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" diff --git a/docs/make.jl b/docs/make.jl index e6a477ec..9bba2d55 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,4 +1,4 @@ -using Documenter, Unitful +using Documenter, Unitful, Dates DocMeta.setdocmeta!(Unitful, :DocTestSetup, :(using Unitful)) @@ -17,6 +17,7 @@ makedocs( "How units are displayed" => "display.md" "Logarithmic scales" => "logarithm.md" "Temperature scales" => "temperature.md" + "Interoperability with `Dates`" => "dates.md" "Extending Unitful" => "extending.md" "Troubleshooting" => "trouble.md" "License" => "LICENSE.md" diff --git a/docs/src/dates.md b/docs/src/dates.md new file mode 100644 index 00000000..08da083e --- /dev/null +++ b/docs/src/dates.md @@ -0,0 +1,133 @@ +```@meta +DocTestSetup = quote + using Unitful +end +``` +# Interoperability with the `Dates` standard library + +[Julia's `Dates` standard library](https://docs.julialang.org/en/v1/stdlib/Dates/) provides data types for representing specific points in time `Date`/`DateTime` and differences between them, i.e., periods. Unitful provides methods for using period types from the `Dates` standard library together with `Quantity`s. + +## Support for `Dates.FixedPeriod`s + +The `Dates.FixedPeriod` union type includes all `Dates.Period`s that represent a fixed period of time, i.e., `Dates.Week`, `Dates.Day`, `Dates.Hour`, `Dates.Minute`, `Dates.Second`, `Dates.Millisecond`, `Dates.Microsecond`, and `Dates.Nanosecond`. These types can be converted to `Quantity`s or used in place of them. + +!!! note + `Dates.Year` does not represent a fixed period and cannot be converted to a `Quantity`. While Unitful's `yr` unit is exactly equal to 365.25 days, a `Dates.Year` may contain 365 or 366 days. + +Each `FixedPeriod` is considered equivalent to a `Quantity`. For example, `Dates.Millisecond(5)` corresponds to the quantity `Int64(5)*u"ms"`. A `FixedPeriod` can be converted to the equivalent `Quantity` with a constructor: + +```@docs +Unitful.Quantity(::Dates.FixedPeriod) +``` + +In most respects, `FixedPeriod`s behave like their equivalent quantities. They can be converted to other units using `uconvert`, used in arithmetic operations with other quantities, and they have a `unit` and `dimension`: + +```jldoctest +julia> using Dates: Hour + +julia> p = Hour(3) +3 hours + +julia> uconvert(u"s", p) +10800 s + +julia> p == 180u"minute" +true + +julia> p < 1u"d" +true + +julia> 5u"s" + p +10805 s + +julia> 210u"km" / p +70.0 km hr^-1 + +julia> unit(p) === u"hr" +true + +julia> dimension(p) +𝐓 +``` + +Conversely, a `FixedPeriod` can be created from a quantity using the appropriate constructor, `convert`, or `round` methods. This will fail (i.e., throw an `InexactError`) if the resulting value cannot be represented as an `Int64`: + +```jldoctest +julia> using Dates: Day, Hour, Millisecond + +julia> Millisecond(1.5u"s") +1500 milliseconds + +julia> convert(Hour, 1u"yr") +8766 hours + +julia> Day(1u"yr") +ERROR: InexactError: Int64(1461//4) +[...] + +julia> round(Day, 1u"yr") +365 days +``` + +## Support for `Dates.CompoundPeriod`s + +The `Dates` standard library provides the `Dates.CompoundPeriod` type to represent sums of periods of different types: + +```@repl +using Dates: Day, Second +Day(5) + Second(1) +typeof(ans) +``` + +Unitful provides facilities to work with `CompoundPeriod`s as long as they consist only of `FixedPeriod`s. Such `CompoundPeriod`s can be converted to `Quantity`s using `convert`, `uconvert`, or `round`: + +```@jldoctest +julia> using Dates: Day, Second + +julia> p = Day(5) + Second(1) +5 days, 1 second + +julia> uconvert(u"s", p) +432001//1 s + +julia> convert(typeof(1.0u"yr"), p) +0.01368928562374832 yr + +julia> round(u"d", p) +5//1 d + +julia> q = Month(1) + Day(1) # Month is not a fixed period +1 month, 1 day + +julia> uconvert(u"s", q) +ERROR: MethodError: no method matching Quantity{Rational{Int64},𝐓,Unitful.FreeUnits{(s,),𝐓,nothing}}(::Month) +[...] +``` + +However, not all operations that are defined for `FixedPeriod`s support `CompoundPeriod`s as well. +The reason for that is that a `CompoundPeriod` does not correspond to a specific unit: + +```@jldoctest +julia> p = Day(365) + Hour(6) +365 days, 6 hours + +julia> unit(p) # A CompoundPeriod does not have a corresponding unit ... +ERROR: MethodError: no method matching unit(::Dates.CompoundPeriod) +[...] + +julia> dimension(p) # ... but it does have a dimension +𝐓 + +julia> Quantity(p) # As a result, there is no Quantity type associated with it ... +ERROR: MethodError: no method matching Quantity(::Int64) +[...] + +julia> T = typeof(1.0u"hr"); T(p) # ... but it can be converted to a concrete time quantity +8766.0 hr +``` + +Consequently, any operation whose result would depend on the input unit is not supported by `CompoundPeriod`s. For example: + +* `+(::Quantity, ::CompoundPeriod)` and `+(::CompoundPeriod, ::Quantity)` error, since the unit of the result depends on the units of both arguments. +* `div(::Quantity, ::CompoundPeriod)` and `div(::CompoundPeriod, ::Quantity)` work, since the result is a dimensionless number. +* `mod(::CompoundPeriod, ::Quantity)` works, but `mod(::Quantity, ::CompoundPeriod)` does not, since the second argument determines the unit of the returned quantity.