purescript-datetime icon indicating copy to clipboard operation
purescript-datetime copied to clipboard

Some questions regarding durations

Open stefanholzmueller opened this issue 8 years ago • 7 comments
trafficstars

  1. There is Data.Time.Duration and also Data.Interval.Duration and I wonder what the difference is. Data.Time.Duration is used for functions like adjust and diff, while Data.Interval.Duration seems to be mostly about parsing and formatting of ISO8601 durations? Is one of them deprecated? Is there a conceptual difference that I fail to see?

  2. Is there a way to format durations in a human-readable fashion? E.g. neither "643257 milliseconds" nor "0,051 days" but in a multi-unit format like "2 days, 15h, 45min"? (this is probably related to purescript formatters, but the calculation might belong to this package)

  3. I realized that the documentation in Pursuit is not up-to-date (the latest version is 3.2.0). Could somebody please update it?

stefanholzmueller avatar Nov 04 '17 11:11 stefanholzmueller

  1. Interval durations are relative - it ambiguous to have a "month long" duration unless you have a start date to go from also.
  2. Pretty printing isn't covered by this library at all, so no there's nothing here to help with that. purescript-formatters would be a good place for that, but currently I think it only supports ISO8601 style, which is probably more unreadable than "643257 milliseconds" :smile:
  3. Anyone can do this actually, pursuit doesn't require that the library author(s) are the ones to upload the docs. But yep! I'll fix the build to restore auto-publishing (we weren't sure what the problem was until recently).

garyb avatar Nov 04 '17 12:11 garyb

  1. That explanation certainly helped. Now I see the subtleties.

  2. Yeah, I already had a look at purescript-formatters, and as you say, it only does ISO8601 formatting on interval durations, while I want to work with Data.Time.Duration. I guess I have to implement it myself. If you have thoughts what an implementation in purescript-formatters should look like, feel free to discuss this with me.

  3. Ah... next time I will try it myself. But of course an automated solution is better. I see it is updated now. :+1:

Thanks for your answers @garyb!

stefanholzmueller avatar Nov 06 '17 18:11 stefanholzmueller

(1) is pretty unfortunate though, you opening this issue made me think about ways of unifying the two again (albeit so that Month and Year are excluded from "time durations"). I'm not sure there's a good reason that time durations are implemented as distinct types + class rather than just as an ADT, for instance. I have no solid plans on that yet though :wink:

For (2), I'm also not too sure. I wonder if perhaps there is a component of that that it would make sense to have in this library after all - since we'll want to do some logic to split a duration into its largest integer components for that kind of display, it might be useful for other things too. Perhaps a collection of functions like totalDays :: Duration d => d -> Int or something. I'm not really sure how much flexibility would be needed in formatting options for printing a date, I guess there are a few options that make sense, but probably not a full on grammar like we have for date formatting, etc.

garyb avatar Nov 06 '17 20:11 garyb

I'll reopen this for now since there might be some stuff to discuss, and we can close it when it gets resolved as to whether we add functions here or whatever.

garyb avatar Nov 06 '17 20:11 garyb

  1. I have no plans to alter the design as well. But I believe we should clarify the difference between both Durations in the documentation. I'll think about it.

  2. Your Duration d => d -> Int function is an interesting idea! So totalHours of a duration of 1.1 days would be 2? I thought about this way to long, and here are some observations I got:

a. That bunch of functions only makes sense together, not alone. In the above example, 2 is not a meaningful result by itself.

b. The return values are guaranteed to lie in a certain range, and maybe the types should reflect this? I'm not a huge fan actually, but this library uses bounded enums in Data.Time.Component, too. Of course a duration component is not the same as a time component. Still, maybe we should reuse that concept.

c. Durations can be negative, so this conflicts with b. already. One solution for this and a. would be to return a combined "multi-unit duration" including sign. Or just integers which may be negative, to be handled by the caller.

d. Not really satisfied with the names, e.g. totalHours since in my example one might expect 26 as result. Maybe hourComponent would be clearer.

For formatting durations, I can think of relative "timestamps" like one hour ago, in 30 minutes (very human-readable, just one unit, pluralization, localization etc.); and also configurable formats like -12:34:56.789 or maybe 12d, 23h and 34min. Differences to date/time formats:

  • Negative durations
  • Neat human-readable stuff
  • Displayed units depending on the value of the duration, but probably the user can just use different formatters for different ranges of values

So yeah, I think functions that split a duration into components of different units would be enough to realize that.

stefanholzmueller avatar Nov 07 '17 19:11 stefanholzmueller

Your Duration d => d -> Int function is an interesting idea! So totalHours of a duration of 1.1 days would be 2?

Actually, I hadn't thought properly about it - totalHours (Days 1.1) would return 26 for what I had in mind, which isn't super useful, as you'd have to subtract the total of the "unit above" at each step while pretty printing.

Maybe just a function durationComponents then? That accepts a duration and returns a record with number of days, hours, minutes, etc. split out. The values in the record could still use the normal Days, Hours, etc. types - those types do admit non-integer values still of course, but the nature of the function (and a doc comment) would suffice perhaps? (And would admit negative values, unlike the time components).

garyb avatar Nov 07 '17 20:11 garyb

I like durationComponents.

By now I pretty much convinced myself that negative numbers as duration components are a bad idea. ;) For all formatting purposes I can imagine, I would not want to deal with a bunch of negative numbers. Not sure how to represent the sign, the lazy way would be negative :: Boolean... or maybe something more fancy like data Sign = Past | Future.

Thinking about it some more, should durations really be negative, or are they supposed to be absolute, like distances?

For the duration components, I'd prefer Int or Enum values over numbers. Maybe just use the types in Data.Time.Component. Arguments against using regular numbers:

  • Even if we'd document everything, the types would be misleading.
  • Callers might need to convert them to Int anyways, which is a bit cumbersome. I don't think the formatter should need to calculate with those numbers.

Maybe the best thing would be to first discuss this over at purescript-formatters and "drive" the API from the consumer's perspective.

stefanholzmueller avatar Nov 08 '17 07:11 stefanholzmueller