José, thank you. I have implemented Cldr.Calendar.strftime/2 as you suggested and published it as part of ex_cldr_calendars 2.0. With your agreement I'll submit a PR for option (3) for core team consideration.
On Thursday, January 30, 2025 at 7:53:16 PM UTC+11 José Valim wrote: > > Yes, the same issue with month of year which I mentioned briefly above. > > Do we have the same issue with "month of year" in that it is representing > the cardinal month instead of the ordinal one? > > > Option (4) isn't ideally in scope for ex_cldr since > Cldr.DateTime.to_string/3 is the canonical CLDR standard formatter. > > WDYM? If that's the standard formatter, does it call Calendar.strftime > behind the scenes? Regardless, could you add Cldr.DateTime.strftime or > would that violate some CLDR API rule/principles? > > --- > > Option 3 is something we could accept in Elixir but option 4 means you can > deliver the feature today, rather than in ~4 months. :) > > > *José Valimhttps://dashbit.co/ <https://dashbit.co/>* > > > On Thu, Jan 30, 2025 at 9:48 AM Kip <kipc...@gmail.com> wrote: > >> > However, I believe the issue above is not specific to day_of_week? >> >> Yes, the same issue with month of year which I mentioned briefly above. >> So I don't believe option (1) and (2) would work for month of year. >> >> Option (3) would be my preference, but arity-checking isn't beautiful I >> agree. >> Option (4) isn't ideally in scope for ex_cldr since >> Cldr.DateTime.to_string/3 is the canonical CLDR standard formatter. >> >> If (1) and (2) won't work (because of the same issue for both day of week >> and month of year) and (3) and (4) aren't considered acceptablethen: >> >> (a) I'll submit a PR to update the documentation for strftime/3 to note >> the behaviour when the calendars first day of week isn't Monday >> (b) I'll Document in ex_cldr_calendars the importance of passing in a >> calendar to `MyApp.Cldr.Calendar.strftime_options!/1` for localised >> calendars >> >> On Thursday, January 30, 2025 at 6:32:41 PM UTC+11 José Valim wrote: >> >>> I can think of a few options: >>> >>> 1. Make day_of_week return a cardinal value in this case by passing >>> :monday as argument to Date.day_of_week >>> 2. Same as above but make the starting day_of_week an option, so you >>> could return starting_day_of_week as part of your options (and you will >>> probably default to :monday on all of them anyway) >>> >>> However, I believe the issue above is not specific to day_of_week? If it >>> is not: >>> >>> 3. Change all callbacks functions in strftime to optionally receive a >>> calendar. We could check the function arity and dispatch accordingly >>> 4. Same as above but you do it in CLDR.strftime, which you add, and wrap >>> all functions to receive the Calendar >>> >>> My preference, for simplicity, would be 1 or 2, probably 2 for backwards >>> compatibility. >>> >>> *José Valimhttps://dashbit.co/ <https://dashbit.co/>* >>> >>> >>> On Thu, Jan 30, 2025 at 3:20 AM Kip <kipc...@gmail.com> wrote: >>> >>>> Hmm, I suppose the flaw in my argument is that the optional argument >>>> functions aren't really callbacks, and they are part of the public API. >>>> Which means this is a breaking change for anyone using a function value >>>> for >>>> an option. >>>> >>>> On Thursday, January 30, 2025 at 12:52:42 PM UTC+11 Kip wrote: >>>> >>>>> *Proposal summary* >>>>> >>>>> Change the callback function signature for `Calendar.strftime/3` >>>>> options to pass both a number and the first arguments calendar. >>>>> >>>>> *Explanation* >>>>> >>>>> Today `Calendar.strftime/3` allows a function to be provided as an >>>>> option to any of the keywords. This is very helpful when working with >>>>> localised calendars because a simple function call can return all the >>>>> data >>>>> relevant to the localised date. For example: >>>>> >>>>> iex> Calendar.strftime ~D[2020-01-30 Cldr.Calendar.US], "%a", >>>>> MyApp.Cldr.Calendar.strftime_options!() >>>>> “Fri" >>>>> >>>>> But there’s an issue: That date is actually a Thursday, not Friday! >>>>> So what’s going on? Internally `Calendar.strftime/3` is calling >>>>> `Date.day_of_week/1`. That function returns a number representing the nth >>>>> day of the calendar-relative week (so-called ordinal day). There is the >>>>> same issue with month of year because not all calendars start in January. >>>>> For example, the Australia tax year calendar starts in July. >>>>> >>>>> Since the US official calendar starts its weeks on Sunday - unlike >>>>> Calendar.ISO which starts its weeks on Monday (like many territories) - >>>>> the >>>>> day name lookup failed to show the correct result. This is because the >>>>> callback didn’t have the calendar context to know what the default >>>>> start-of-week day is. >>>>> >>>>> Now that can be worked around by specifying the calendar in >>>>> MyApp.Cldr.Calendar.strftime_options!/1 >>>>> like this: >>>>> >>>>> iex> Calendar.strftime ~D[2020-01-30 Cldr.Calendar.US], "%a", >>>>> MyApp.Cldr.Calendar.strftime_options!(calendar: Cldr.Calendar.US) >>>>> “Thu" >>>>> >>>>> But that feels an error prone. Perhaps it would be better to pass the >>>>> calendar of the date/datetime/time argument to the callback functions >>>>> instead? Today those functions receive a number only. This proposal is >>>>> to >>>>> have the functions receive both a number and the calendar of the first >>>>> argument (which might be nil). This would give appropriate context to the >>>>> 4 >>>>> out of the 5 callback functions that would benefit from it (2 each for >>>>> month name and day names). >>>>> >>>>> *Precedent* >>>>> >>>>> This would be a breaking change for the callback signature - but not >>>>> for the Calendar.strftime/3 public function. There is some limited >>>>> precendent. For example when the `Calendar.day_of_week/3` callback >>>>> changed >>>>> to be `Calendar.day_of_week/4`. That change affected the implementation >>>>> of >>>>> alternative calendars, but it did not affect consumers of those calendars. >>>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "elixir-lang-core" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to elixir-lang-co...@googlegroups.com. >>>> To view this discussion visit >>>> https://groups.google.com/d/msgid/elixir-lang-core/583251f8-b182-4133-8a9d-03bc3b96ae74n%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/elixir-lang-core/583251f8-b182-4133-8a9d-03bc3b96ae74n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "elixir-lang-core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to elixir-lang-co...@googlegroups.com. >> > To view this discussion visit >> https://groups.google.com/d/msgid/elixir-lang-core/be73d5e9-2451-48c9-a718-5a961eebfc48n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/elixir-lang-core/be73d5e9-2451-48c9-a718-5a961eebfc48n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/elixir-lang-core/154e46b6-b7c7-4f64-8e4a-c41140767bcfn%40googlegroups.com.