haskell / time

A time library
http://hackage.haskell.org/package/time
Other
118 stars 78 forks source link

Year and week number convert into UTCTime on thursday #135

Closed flip111 closed 3 years ago

flip111 commented 4 years ago

original function

utcTimeRoundDownWeek :: UTCTime -> UTCTime
utcTimeRoundDownWeek time =
  let format = "%Y %W" -- https://man7.org/linux/man-pages/man3/strptime.3.html
  in parseTimeOrError False defaultTimeLocale format $ formatTime defaultTimeLocale format time

Minimal reproduce

buildTime defaultTimeLocale [('W', "35"), ('Y', "2020")] :: Maybe UTCTime

today 6 september 2020 is week 36 (normally), but week 35 when starting to count from 0 (programming)

Output

Just 2020-09-03 00:00:00 UTC

Wanted output & expected output variant 1 (reset to monday)

Just 2020-08-31 00:00:00 UTC

Alternative expected output (current day "sunday" of any given week number)

Just 2020-09-06 00:00:00 UTC

In my opinion when '%W' is given and '%w' is not given, '%w' should default to 0

AshleyYakeley commented 3 years ago

In my opinion when '%W' is given and '%w' is not given, '%w' should default to 0

That's an awkward special case. There may be a more general approach to this.

flip111 commented 3 years ago

What would be the other cases, that makes this one special ?

On Wed, Sep 30, 2020, 10:20 Ashley Yakeley notifications@github.com wrote:

In my opinion when '%W' is given and '%w' is not given, '%w' should default to 0

That's an awkward special case. There may be a more general approach to this.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/haskell/time/issues/135#issuecomment-701240066, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARD7AHFJALSKAPW222JORDSILS3VANCNFSM4Q4WRWJQ .

AshleyYakeley commented 3 years ago

So generally if information is missing, it's taken from the Unix epoch of 1970-01-01, which was a Thursday. But you want an exception here, right?

I'm thinking there may be a more general approach that makes it easier to specify defaults.

flip111 commented 3 years ago

Eh that's strange i thought that UTCTime had a totally different data structure that was not based on unix epoch. In any case it would be very rare that people would want things to default to unix epoch. I think they would prefer this order:

  1. Have it default to "the start of the biggest unit specified" so if the biggest unit is a week then the defaults for day, hour and so on would be monday, 00 .. etc
  2. Have it default to the current time
  3. Have it default to start of julian calendar
  4. Have it default to unix epoch
AshleyYakeley commented 3 years ago

1 is kind of complex, especially since "start of the week" is somewhat ambiguous 2 is impossible (since it's impure) 3, you must mean Gregorian calendar, and it's the same as 4

AshleyYakeley commented 3 years ago

OK, I've come up with a more general solution for this. I've added a new function:

parseTimeMultipleM :: (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> [(String, String)] -> m t

So now you can do this:

parseTimeMultipleM False defaultTimeLocale  [("%u","1"), ("%Y %W", input)]
flip111 commented 3 years ago

I don't understand your solution, but i appreciate you looking into it :)

AshleyYakeley commented 3 years ago

So the idea is that the pair ("%u","1") is equivalent to "Monday". So for the other pair, ("%Y %W", input), which is incomplete by itself, parseTimeMultipleM will pick the Monday of that week.