[Proposal] Calendar behaviour additions to support localisation libraries and other calendar calculations

64 views
Skip to first unread message

Kip

unread,
Jul 10, 2017, 3:03:53 AM7/10/17
to elixir-lang-core
With the new capabilities of Calendar in 1.5 I am now adding date and time localisation to a package I maintain (https://hex.pm/packages/ex_cldr).  

CLDR (http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns) defines a number of symbols to aid formatting and localisation.  Many of these can be supported by the Calendar module (or easily derived).  Some would be better defined in a calendar module - which would imply adding them to the behaviour and to Calendar.ISO.

These functions are:

1. months_in_year(year) which together with the existing days_in_month/2 would allow the calculation of quarters which is relevant in a lot of business contexts
2. week_of_year(date) which returns the week number within which the date occurs.  
3. week_of_month(date) which returns the week of the month within which the date occurs
5. day_of_week_in_month(date) returns the ordinal day (i.e. 2nd in 2nd Wednesday in July)
6. year(date) which returns the effective year in which the date lies.  For example in an ISO Week implementation, the "year" may be different to the "year in the date"

Although my immediate focus is date formatting and localisation, these functions are of themselves relevant for other "calendarists" (is that a word?)   Each of these may have quite specific implementation details related to a given calendar and therefore would seem to be appropriate to be part of the behaviour. 

I've tried to think of only those functions which cannot be readily derived without knowledge of the specific calendar but I know this is a slippery slope - especially with anything to do with time and dates.

Thoughts?

--Kip

José Valim

unread,
Jul 10, 2017, 4:35:18 AM7/10/17
to elixir-l...@googlegroups.com
I am OK with delegating more functions to calendar as long as we have use cases for it. I am also OK with adding a year function but we need to come up with a better name. :)

Thanks for looking into this Kip!


José Valim
Skype: jv.ptec
Founder and Director of R&D

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/20060086-74b8-4a40-bbf4-a160783f94d9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Wiebe-Marten Wijnja

unread,
Jul 10, 2017, 5:15:37 PM7/10/17
to elixir-lang-core
I am all for this!

However, I do have a note about the week-related stuff: 
On one hand, people might expect 'weeks' to be readily available (`:calendar` offers them, and many other libraries in other language environments do). 
On the other, many calendars do not themselves have a notion of weeks. (Weeks are only secondary units of date measurements (years, months, days are the primary ones) and nearly all calendars, all across the globe, use a seven-day week.
Weeks are basically the months of the ISO week date calendar: https://en.wikipedia.org/wiki/ISO_week_date
I wonder how much of the week-related functionality could be defined by just taking a date (in e.g. Calendar.ISO) and converting it into the ISO week date calendar. 

~Qqwy/Wiebe-Marten

Kip

unread,
Jul 10, 2017, 5:48:26 PM7/10/17
to elixir-lang-core
Definitely worth thinking about as an approach for weeks. Some of calendars may make that tricky - I'll need to ponder some more.

1.   "4-5-4" calendar (and its related friends 445 and 544).  This is used extensively by the retail industry (https://nrf.com/resources/4-5-4-calendar).

2.  Another class is the financial period calendars of corporations in the US that get to define their fiscal year.  For example Cisco Inc has a financial year defined as "ends of the last Saturday of July".  Its fiscal year 2017 for example, starts on July 31st 2016. (also to note the effective year is different from the gregorian year of the day in question).  This is a class of calendar that requires configuration information - I haven't quite worked out the right strategy for these calendars yet (Date.new/3 won't fit these cases as is)

Then there is the locale-specific understanding of a week:

1.  Starts on a Monday, Saturday or Sunday

2.  1st week starts as the first calendar week which contains four days of the new year

3.  1st week starts as the week in which January 1st occurs

I think these situations are likely to make basing weeks along the ISO Week strategy a bit tricky.

Wiebe-Marten Wijnja

unread,
Jul 11, 2017, 9:53:36 AM7/11/17
to elixir-lang-core
Yes, I think those arguments are arguments for allowing weeks to be specified in their own calendar implementations, treating weeks like months.
I'd think Elixir itself should then implement the ISO week date calendar, 
and locale-specific week logic can be put in locale-specific calendar implementation modules. This would also keep the door open for "4-5-4" and friends-based weeks, 10-day based weeks, etc.
Counting in weeks definitely has the same amount of complexity as counting in months in a normal calendar (I am talking about odd leaping rules here), so it definitely makes sense to use the same or a similar interface for this.

The question then remains to how to make this more user-friendly. Maybe we can add functions on the `Date`-module that take an optional `week_calendar: Calendar.Implementation` as last parameter, that underwater does:

1. Take the Date-struct, and convert it to the given Calendar. (failing as usual if the conversion is not possible because of incompatible calendars)
2. Perform calculations on the resulting struct using the existing Calendar implementation functions, where the 'months' are weeks.
3. Return the desired answer.

Ed W

unread,
Jul 12, 2017, 11:01:55 AM7/12/17
to elixir-l...@googlegroups.com
I think your problem boils down to defining the first day of the "year"?  After that you can simply count days and divide by 7?  Similarly a week end will be defined by (mod(days, 7) == 0)

Perhaps you need a function which takes a year and gives you the date of the start of the year?

Ed W
--
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 on the web visit https://groups.google.com/d/msgid/elixir-lang-core/db80f9b9-a370-4530-a20a-e7fd192902ba%40googlegroups.com.

Kip

unread,
Jul 14, 2017, 9:53:55 AM7/14/17
to elixir-lang-core
@jose, @Qqwy,

I am prototyping some of these implementation details in the next release of my CLDR work.  The nature of a week is indeed a complex beast.  But since José was smart enough to pick ISO calendar as the Elixir implementation the definition of "first week" seems clear.  The first week is that in which the first Thursday falls. (or is the that week with at least 4 days of the new year).

Before I get too far may I ask if this is in agreement?  The reference I am using is https://en.wikipedia.org/wiki/ISO_week_date#First_week with the suggest calculations being https://en.wikipedia.org/wiki/ISO_week_date#Calculation

For other calendars the definition of "first week" is/may be territory specific.  As is "first day" and "weekday". Which is why localisation is such fun ......

--Kip

José Valim

unread,
Jul 14, 2017, 10:14:20 AM7/14/17
to elixir-l...@googlegroups.com
Can you please specify which functions would you like to add to Calendar? first_week(year, month, day) and last_week(year, month, day)? Or is it first_week(year) and last_week(year)?




José Valim
Skype: jv.ptec
Founder and Director of R&D

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/56690dd1-c89b-4e28-963a-fcd54c72494b%40googlegroups.com.

José Valim

unread,
Jul 14, 2017, 12:39:56 PM7/14/17
to elixir-l...@googlegroups.com
Or alternatively you can implement a Calendar.ISOWeek where month is used to represents weeks. If you do so, then I believe the functionality that you need is "first_day_of_the_year(year, month, day)" and "last_day_of_the_year(year, month, day)". "first_day_of_the_month(year, month, day)" and "last_day_of_the_month(year, month, day)" as well as "first_day_of_the_week(year, month, day)" and "last_day_of_the_week(year, month, day)" don't hurt either. This will also help us write things such as "next_month" and "last_month", which can be very convenient.



José Valim
Skype: jv.ptec
Founder and Director of R&D

Reply all
Reply to author
Forward
0 new messages