# Operations with time duration

I am relatively new to Julia. I don’t see a way to do the following in Julia in an easy way, like en excel…
t = 1h5m2s
average per Km = t/5 = 13m0s400ms

Any help?

``````julia> using Dates

julia> t=Time(1,5,2)
01:05:02

julia> Time(t.instant/5)
00:13:00.4
``````
1 Like

Thanks… Very simple. But it works only if it less than 24 hours… For example, it does not work in the following example.
t = 26h3m5s
t/5 = 5h12m37s

``````julia> canonicalize(Dates.CompoundPeriod((Second(Hour(26)) + Second(Minute(3)) + Second(5))/5))
5 hours, 12 minutes, 37 seconds
``````

That’s super verbose. Can’t you just do

``````(Hour(26) + Minute(3) + Second(5)) / 5
``````

or something like that?

There’s no `/` for `CompoundPeriod`, which I guess is why the above goes via `Second`. I wouldn’t be surprised if there was a more ergonomic formulation, but equally if there isn’t I’d probably just define a one line in my code.

Seems like a typical job for type promotion? Everything should promote to seconds. Oh well.

These types intentionally don’t promote to a common type because they represent the difference between two points in time in a calendar, which is not always a fixed length of time. e.g. because of leap seconds, some minutes are 61 seconds long.

For the OP’s problem, I’d suggest using Unitful.jl instead which specifically deals with measurements not calendar periods.

5 Likes

I think that in the same way you can add or subtract duration, you should be able to divide or multiply by a number. I am surprised, that something that it is easily done in excel, it can not be easily replicated in Julia, a language that is known to be concise. I found also a similar issue from someone in 2018… I am not the only one having this issue.

When dealing with calendar periods, which is what Dates is for, a period is a discrete indivisible unit. It doesn’t make sense to talk about “half a minute” because how do you add half a minute to the time 12:00:00? The answer is not 12:00:30 because a minute is sometimes 61 seconds long.

See Dates · The Julia Language for more detail.

You can use Unitful.jl though:

``````julia> using Unitful

julia> t = 1u"hr" + 5u"minute" + 2u"s"
3902 s

julia> t/5
780.4 s
``````
2 Likes

I disagree. Dates consider “duration” as part of the methods. As such basic operations should be included. It should not difficult to convert internally to seconds or milliseconds and express the results in a compact way as compound period. No need to go to another library. Other languages do so. Its just my opinion.

How long do you want the duration of `Month(1) / 2` (i.e. a duration of 1 month divided in half) to be? Depending on which month you’re talking about, the result will be different - it can be 14 days (or 14.5 in leap years), 15 days or 15.5 days in a typical gregorian calendar (not to mention other calendars).

The point is that such arithmetic doesn’t make sense in isolation - you have to place it at a specific point in time to make sense of it, which is why only addition/subtraction of Dates + Period is supported.

That being said, there is a fallback in the form of integer division (using `div` or `÷` in operator form), which throws away the cutoff altogether, but keeps the same type as to prevent the sort of confusion that can happen with e.g. my example using `Month` from above.

I think what you’re looking for is a way to deal carefully with time, and only informally with dates. Dates are actually very complicated, as it is not easy to compute the duration in seconds between say Jan 1, 1580 and now. There was the Julian calendar, then the Gregorian calendar, leap years, leap seconds, etc. Durations are also complicated by time zones, for example the time between midnight January 1 and midnight July 1 can depend on whether the location observes daylight savings. A serious date package may try deal with some of these things very carefully, e.g. ISO 8601 for Dates.jl, and they are not wrong to do so.

If Excel happily computes what you want, my guess is that it has adopted some convention that works okay for most people. But unless you know the specification, it might give you unexpected results. Excel was originally intended for business uses, and it might not be great for computing the date and time for the television broadcast of your Mars probe landing 10^8 seconds from now. It sounds like you’re mostly concerned with hours, minutes, etc. where one needn’t be concerned with dates, and Unitful.jl may do the job, as suggested by @cjdoris.

1 Like

I am dealing with operations/activities where the time is measured mainly in days, hours and seconds and where some calculations like average need to be calculated. Months, years are not needed.

What is it about Unitful.jl that doesn’t work for you? It also has days:

``````julia> using Unitful

julia> (1u"d" + 2u"hr" + 3u"minute" + 5u"s")/5
18757.0 s
``````
2 Likes

Some days are not 24 hours. For example, Leap second - Wikipedia

Yes… but how I come back to a compound date expression like 18757s = 5h 12m 37s. It seems complicated and verbose… For this type of things, Julia could offer something basic, as I said at the beginning. In excel you just have two lines.
t = 26h3m5s
t/5 = 5h12m37s

The basic version you’re looking for is Unitful.jl. Julia doesn’t use these sorts of compound time slices internally and having it as part of Base would mean you’d only get updates with a new julia version (instead of more often, since Unitful can decide when they want to publish a new version).

In general, julia’s Base is more lean than other languages (e.g. Python or Excel), but that doesn’t mean that using code from a package is a worse deal. It’s a more flexible situation all around because it means bugs specific to that code are fixed quicker and you’ll get those updates more often and generally sooner than a whole julia release cycle (which can take quite a while).

The compound periods you’re looking for are already part of Unitful.jl, see their docs here.

The base version means for me “quality”, “commitment” and “standards”. Many packages unfortunately are developed by one person that 1) may or not provide good documentation 2) may or not provide frequent updates 3) may or not abandon the project. I rather prefer personally to include as much as possible in the base version. With regards to unitful.lj, I do not find an easy way to do the following two lines…
t = 26h3m5s
t/5 = 5h12m37s

Not sure why Rafael deleted his post, but something like his deleted suggetion would work. Similarly, you can just wrap the seconds that Unitful gives you in `Second` and `canonicalize`:

``````julia> t = 26u"hr" + 3u"minute" + 5u"s"
93785 s

julia> t/5
18757.0 s

julia> canonicalize(Second(t.val))
5 hours, 12 minutes, 37 seconds
``````

Or you can define that as a function as well

``````julia> Dates.canonicalize(x::Quantity{Int64, 𝐓, Unitful.FreeUnits{(s,), 𝐓, nothing}}) = canonicalize(Second(x.val))

julia> canonicalize(t/5)
5 hours, 12 minutes, 37 seconds
``````
1 Like