massivefermion / birl

datetime handling for gleam
https://hex.pm/packages/birl
Apache License 2.0
72 stars 9 forks source link

Convert to and from Erlang timestamp tuples #6

Closed lpil closed 1 year ago

lpil commented 1 year ago

Hello!

Are there functions to convert to and from Erlang timestamp tuples?

Thanks, Louis

massivefermion commented 1 year ago

I have to_parts and from_parts that did just that, with the only difference being those also included milliseconds and offset string. But I didn't think the interface was nice enough to be public, so now I have set_date, get_date, set_time, get_time, set_offset and get_offset. Of course set_time and get_time still get and return the millisecond part too. Of course set_date and set_time actually take a Time value and change the date and time on it. But I guess if you use it with unix_epoch, it behaves the same!

lpil commented 1 year ago

Is get_date etc for working with Erlang dates? Perhaps it would be good to have the name Erlang in the name?

massivefermion commented 1 year ago

no, they're not specific to erlang. they all work the same for both targets.

lpil commented 1 year ago

Sorry, I've been unclear. The Erlang calendar types are poorly designed so we want to dissuade their use as much as possible. Using a nice, short, and generic name like "set_date" implies that it's the standard Gleam date type, but really we want Gleam programmers to never use this function unless they are writing FFI code that forces them to.

massivefermion commented 1 year ago

So if I understand correctly, you want to dissuade people from using {{Year, Month, Day}, {Hour, Minute, Second}} and by extension {Year, Month, Day} and {Hour, Minute, Second}? But actually when I added set_date and set_time I had in mind a use case that I was already encountering at my work so I think it would actually be useful to use those functions, even if you're not targeting Erlang. For example imagine you have a list of items that include a created_at field and you need to search for the ones that were created today or this month. You can just get now() and use set_time or set_date to get the start and end of the current day or month. Of course we could have separate set_year, set_month, etc. but I thought that would just be too many functions for this use case so I just added use_date and use_time. I did think about having a specific type Date to use for this case but that would imply the corresponding type would be Time for the time part but that is already used for the main opaque type. Maybe I could change the main type's name to DateTime to solve that but I'm not sure that's the right name for it. What do you think about set_date(time: Time, year: Int, month: Int, day: Int) and a similar signature for set_time? Also, is it really necessary to have specific functions to use with Erlang's datetime tuples? The existing functions already cover that, people just need to separate the date and time, or in case we end up using set_date(time: Time, year: Int, month: Int, day: Int)(and similar for time), they would need to separate every single part which would be dissuading enough!

lpil commented 1 year ago

you want to dissuade people from using {{Year, Month, Day}, {Hour, Minute, Second}} and by extension {Year, Month, Day} and {Hour, Minute, Second}?

Yes, totally. It's a very old API that doesn't conform with conventions of any modern BEAM language. We don't want to inherit this technical debt from Erlang.

Having set_date etc functions would be fine, but we'd want to use a normal Gleam record for that rather than the strange and confusing tuple.

pub type Date {
  Date(day: Int, month: Month, year: Int)
}

pub type Month {
  Jan
  Feb
  Mar
  Apr
  May
  Jun
  Jul
  Aug
  Sep
  Oct
  Nov
  Dec
}

Also, is it really necessary to have specific functions to use with Erlang's datetime tuples?

I think it'd be handy, otherwise every package that uses birl and does Erlang FFI will need to copy the same conversion boilerplate.