chansen / p5-time-moment

Time::Moment represents an exact moment in time.
32 stars 8 forks source link

Time::Moment-compatible duration and duration parser? #38

Open sshine opened 5 years ago

sshine commented 5 years ago

Hi Christian / others

First, two needs and then two questions.

1) Parser: I've had to parse durations like "2 days ago", "3 months ago", etc. and have only been able to find DateTime::Format::Natural which returns a DateTime object. It seems that a better thing to return would be a DateTime::Duration, so I don't first have to pick the difference -- after all, "2 months ago" is rarely exactly two months ago, but rather a rounded-off approximation, so the intermediate DateTime object is incorrectly accurate, whereas a duration-like object may naturally retain the imprecision.

2) Duration: I think that Time::Moment does not have a similar Duration-like type to represent differences (or I haven't found it), but rather the delta_* functions. These are much simpler, but don't compose as easily. For example, if I want to pretty-print the duration between two Time::Moment objects, I'll have to do a bunch of elsifs on delta_years, delta_months, etc. all the way down until the difference is above 0.

So my questions are:

1) Do you see a future where durations between two Time::Moments are represented as a type?

2) If so, would it make sense to build a duration parser and pretty-printer that returns this type?

sshine commented 5 years ago

@chansen: If you provide some guidance with regards to your design philosophy for Time::Moment, I could provide a supplemental library for dealing with Time::Moment-compatible durations.

poti1 commented 2 years ago

I am looking to replace DateTime::subtract_datetime() with a Time::Moment equivalent, but was unsuccessful so far.

I tried a simple solution to take the delta seconds and divide by ONE_YEAR, then ONE_MONTH, then ONE_HOUR, then ONE_MINUTE. This is not a suitable for a DateTime::subtract_datetime() replacement.

DateTime::subtract_datetime() can detect that from 02-01-2022 until 03-01-2022 is just 1 month. The simple solution is close, but would assume that a month is ONE_YEAR/12 so that duration would be 1 month, and maybe some hours as well.

sshine commented 2 years ago

Since there isn't an equivalent to DateTime::Duration for Time::Moment, you could take the difference in (seconds | days) between two Time::Moments and construct a DateTime::Duration. Since the difference between two dates can mean many things, and the precision is not implied, perhaps this is or isn't sufficient.

poti1 commented 2 years ago

I tried that, but its not quite the same. From March 17th to April 17th is exactly 1 month using DateTime::subtract_datetime. Using a simple seconds calculation may calculate 1 month +/- some hours.

So, it's close, but not quite enough to allow me to swap out DateTime altogether.

sshine commented 2 years ago

It would open up for a lot of complexity where you can't really say if time difference is correct, or even to what degree it is approximate.

Making so that 2022-03-17 + 1 month = 2022-04-17 only has few gotchas,

If you want a library to support 2022-04-17 - 2022-03-17 = 1 month, and the library specifically only allowed you to express calendar dates without time, then that would only involve the same amount of gotchas. But because a Time::Moment is the combination of a calendar day and a valid time on that day, measuring the difference between two Time::Moments involves both calendar and time.

Specifically, any inclusion of time beyond the date itself clutters the picture significantly because there is much more complexity when it comes to time. Leap years, leap seconds, timezones, historical changes to when timezones apply based on geo-coords, the rotation of the Earth around its axis relative to the Sun meaning not all days have the same length, multiple definitions of universal time. Asking "what's the difference between these two moments?" (and not dates) implies some answer to some of these parameters. A library would have to either make implicit assumptions and hope the caller cares neither more or less about them, or include the complexity in the library's design.

The way another time library handles this is by introducing a NominalDiffTime type where all days are 86400 seconds long, a UTCTime that specifically accounts for only leap seconds/years, a LocalTime that includes timezones, and a UniversalTime that corresponds to the UT1 definition of universal time. Specifically, this library also separates the concepts of calendar and time so that you can actually make the simplistic differences without opening the can of time worms to some unspecified degree.

Also,

not quite enough to allow me to swap out DateTime altogether

Right. And that may not happen any time soon unless you fork Time::Moment and start tweaking. :)

sshine commented 2 years ago

I think of Time::Moment as a library that gets the uncontroversial parts right by way of simplicity, and is highly efficient (as far as I remember, the motivation for the creation of the library is that its internal representation is very small). Also, the extent of what the library can do is naturally limited to the original author's use-case(s).

DateTime::subtract_datetime() is a function of high value, without an exact specification.

It's a function that can't easily be correct. Copying it isn't in easy alignment with Time::Moment... I think. :)

poti1 commented 2 years ago

Yes, it certainly is a fast library.

I ended up using Time::Moment for most of the calculations in my code, but still retained the DateTime::subtract_datetime function and I saw considerable improvements.

poti1 commented 2 years ago

I did not see much activity on this module in a while. Any plans (or desires) for working on some of the open issues?

sshine commented 2 years ago

Sounds like the tradeoff I'd also make.

I don't see any plans.