Using Dates module in Julia I am able to transform a Period type object (Hour, Minute, Second, Day etc.) to another Period type as below:
using Dates
julia> convert(Day, Hour(96))
4 days
julia> convert(Second, Hour(20))
72000 seconds
But if I try to convert any CompoundPeriod type object (Hour(2) + Minute(20), Week(3) + Day(5) etc.), it throws an error as below:
julia> convert(Second, Hour(3) + Minute(12))
ERROR: MethodError: Cannot `convert` an object of type Dates.CompoundPeriod to an object of type Second
Here, 3 hours + 12 minutes = 11520 seconds
Is there a Julia function to find the number of seconds (11520 seconds) in this case?
How can I convert a CompoundPeriod type object to Period type in Julia?
I don’t think there is a nice way to do this right now (but it would be good to add it). You can use Dates.tons or Dates.toms to convert a CompoundPeriod to a number in nanoseconds or milliseconds, but it will be a floating-point number, so you might lose some precision. For example, you could do
Don’t know, if this is a good idea. From the docs:
help?> Dates.CompoundPeriod
CompoundPeriod
A CompoundPeriod is useful for expressing time periods that are not a fixed multiple of smaller periods. For
example, "a year and a day" is not a fixed number of days, but can be expressed using a CompoundPeriod.
From this definition it seems clear, why there isn’t such a thing.
Of course, one can argue, that it should be available and do the conversion for those CompoundPeriods, where it is uniquely possible, like for hours+minutes to seconds.
Should it raise an error/exception for year+month e.g. into days?
I didn’t look into your PR, so perhaps you have already thought of all this issues.
As a more general question, I don’t understand what the intention behind CompoundPeriod is.
Could someone explain how / what it is supposed to be used for?
I understand that a CompoundPeriod is a collection of Periods, and that it can be constructed from a Vector{Period}.
However, what can be done with it after this? There is a canonicalize function which converts (assuming I understand correctly) a CompoundPeriod into another CompoundPeriod. It redistributes the quantities assigned to each Period component of a CompoundPeriod in the canonical way.
Beyond that - is there anything else you can do with a CompoundPeriod?
Sorry I’m somewhat confused because I don’t appear to be able to do any of the following things:
convert it to a Period
print it (format it as a String)
convert it to a number of Seconds, either as an integer or floating point number of “seconds”
convert it to a Time or TimePeriod or some other “duration” type
I would have guessed that I should be able to do one or more of the above operations?
The CompoundPeriods.jl package is a third-party package. I would recommend sticking with the Dates standard library for now. (Note that the composite period type is Dates.CompoundPeriod, without an s at the end.)
Regarding your other questions, it’s been a while since I’ve used the Dates standard library (I use Python at work these days), but I can attempt to answer them.
I believe that the Period and CompoundPeriod types should be mostly interchangeable, so you shouldn’t need to do a manual conversion from one to the other.
There is the Dates.format function for formatting times as strings, but note that it only works for subtypes of Dates.TimeType (i.e. Date, Time, and DateTime). Periods, durations, and compound periods are not subtypes of TimeType.
A period or compound period represents a calendar period, which does not have a well-defined duration. So, for instance, Month(1) + Day(1) is a compound period that represents “a month and a day”. But the number of seconds in Month(1) + Day(1) depends on the month that you are talking about. So, the second extractor doesn’t work on a period:
Sorry, to clarify I meant with some customizable format. I was assuming the format function call might work with something like a String to specify the format. eg HH:MM:SS, etc
Ah yes, ok then it’s reasonable such a thing is not implemented. I should have realized this.
Just want to give my 5 cents to this topic, as it came up to me every now and then during work on different projects.
If the duration does not comprise Month or Year you can always convert back to a period. Just make sure you use the lowest occurring unit.
Hence,
convert(Nanosecond, cp)
is a safe bet.
If you are interested in converting to the lowest occurring unit you can define
function toperiod(cp::Dates.CompoundPeriod)::Period
p = Dates.periods(ei)
isempty(p) ? Millisecond(0) : convert(typeof(last(p)), cp)
end
Where I deliberately chose to convert zero compund periods to Milliseconds, as that is (currently) the lowest unit of now().
What I feel is that a large time duration becomes easier to see when it is viewed as CompoundPeriod type.
As example here is a Period (more precisely a TimePeriod) object t
julia> using Dates
julia> t = Second(115920)
115920 seconds
Lots of seconds right!? Looking at this time duration t it is difficult to imagine how long it is! This time duration exceeds a whole day or half day!? The best way to view this duration is by transforming it with larger time units (e.g. Day, Hour etc.). We can do that using canonicalize() function as
julia> canonicalize(t)
1 day, 8 hours, 12 minutes
canonicalize() function transforms the time duration into a visually nice CompoundPeriod object which helps us to understand the length of the time duration better.
Now, while doing calculations with typical time durations, it is not always convenient to work with CompoundPeriod objects, because it can take long time while typing out and we need to think about memory allocations also. That’s why, when necessary and possible, we need to transform the CompoundPeriod objects with smaller atomic units (e.g. Minute, Second, Millisecond etc). In Julia v1.8.0 afterwards we can do that using convert() function. As we see for the CompoundPeriod object cp here