Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Hijri or Jalali or other international calendar in datepicker #2519

Closed
araselahi opened this issue Jan 4, 2017 · 44 comments
Closed
Assignees
Labels
area: material/datepicker feature This issue represents a new feature or feature request rather than a bug or bug fix help wanted The team would appreciate a PR from the community to address this issue needs: discussion Further discussion with the team is needed before proceeding P5 The team acknowledges the request but does not plan to address it, it remains open for discussion

Comments

@araselahi
Copy link

araselahi commented Jan 4, 2017

I think making dateUtil.js injectable, would provide calendar support functionality for Hijri or Jalali or other international calendars in datepicker. Adding fromGregorian and toGregorian date functions to $mdDateLocale service may provide more abstract solution. These functions could be consequently used in dateUtil.js to provide localized date calculation. Currently $mdDateLocale just provide messages, formatters, and parsers for date internationalization but not date conversion.

I volunteer to produce dateUtil or $mdDateLocale for Hijri or Jalali. Please help me how.

@fxck
Copy link
Contributor

fxck commented Jan 4, 2017

There's no datepicker in material2. $mdDateLocale sounds like material. You are probably in a wrong repo.

@araselahi
Copy link
Author

I just saw datepicker on material2 feature status: https://github.com/angular/material2#feature-status
thought that it would inherit the same functionality from material. Hope you take internationalization date conversion into account for new datepicker. We all love material(2) and your great project.

@araselahi araselahi changed the title Supporting Hijri or Jalali or other international calendars in datepicker would be great. Support for Hijri or Jalali or other international calendar in datepicker Jan 4, 2017
@fxck
Copy link
Contributor

fxck commented Jan 4, 2017

The problem with datepicker, as mentioned in its issue, is that there are no specs(for desktop version anyway) in material design for it.. so until google designers create those, there won't be no official date/timepicker implementation. Sadly.

But I'm pretty sure that once the spec is done, internationalization will be taken into account.

@araselahi
Copy link
Author

araselahi commented Jan 4, 2017

Internationalization date conversion may not affect visual design of datepicker. It just refer to how cells arrange according to the native calendar rules, mainly the same functions as currently exist in dateUtil, but with native alternative principals. About the visual customization, task already has been done gracefully in $mdDateLocale.

@jelbourn
Copy link
Member

We're designing the datepicker now. We likely will only be able to support the Gregorian calendar in the initial version, but it's worth thinking about in the design.

@araselahi
Copy link
Author

araselahi commented Jan 27, 2017

At the moment it may not important to support any special native calendar. The important point about this feature is to make the logic of date conversion 'injectable'. Then every folk will know how to implement their native conversion logic providers. Although I had some suggestions above, but as a designer, you know better how to construct the structure. Thanks Jeremy, for taking it into account and for your grate project.

@mmalerba
Copy link
Contributor

I'll have a design doc to share shortly, it would be great if you could take a look and let me know if you think the design is flexible enough to support this.

@araselahi
Copy link
Author

of course, it would be my pleasure.

@mmalerba
Copy link
Contributor

mmalerba commented Feb 3, 2017

@araselahi
Copy link
Author

I have just seen the notification in my email. I will get back to you soon.

@araselahi
Copy link
Author

araselahi commented Feb 4, 2017

@mmalerba 'CalendarLocale injectable' and 'Internationalization' sections currently include the definition only about the word translation and visual parsing and formatting but not other nationality date conversion logic. In other calendars, days calculation completely different from Gregorian. So I guess we need all the logic in dateUtil.js such as getFirstDateOfMonth, getNumberOfDaysInMonth and so on could be replaceable according to the other international calendar to determine how the days to be rendered on date picker. I think with this suggested feature, it would be a magic date picker for other folks. I am not sure the new SimpleDate data type could support other international calendar date because it is still subset of Gregorian calendar date. Am I right?

@mmalerba mmalerba added the feature This issue represents a new feature or feature request rather than a bug or bug fix label Apr 11, 2017
@mmalerba
Copy link
Contributor

@araselahi I'd like to find some way to allow using moment.js objects instead of SimpleDate when the library is loaded. moment.js already has plugins for working with other languages. I still need to find the best way to do this though

@peymanebrahimi
Copy link

As @araselahi mentioned, it is not a matter of translation from English to another language.
In Persian calendar for example the whole logic of the date system is different.
2017-April-15 may be translated into 2017 آپریل 15 which has nothing to do with Persian calendar for our daily usage which is 1396-1-26 yyyy-MM-dd.
It is 26th day of the first month of the year 1396, but in Gregorian calendar it is 15th of the forth month of the year 2017.

@araselahi
Copy link
Author

@peymanebrahimi it completely depends on how to implement Moment.js. If the output of configured Moment.js object was rendered on the final date picker surface as @mmalerba designed for, that would be great. Please check it out:
https://momentjs.com/docs/#/plugins/jalaali/

@jelbourn
Copy link
Member

jelbourn commented Jun 6, 2017

@mmalerba does what we have now actually support different calendars, or are there assumptions about the Gregorian calendar baked in?

@jelbourn jelbourn added the P5 The team acknowledges the request but does not plan to address it, it remains open for discussion label Jun 6, 2017
@mmalerba mmalerba added the help wanted The team would appreciate a PR from the community to address this issue label Jun 8, 2017
@mmalerba
Copy link
Contributor

mmalerba commented Jun 8, 2017

I think we still have some assumptions baked in, but it should be easy enough to change them to settings in the DateAdapter going to mark this one as good for community contribution. It would be nice to have someone who knows more about other calendars help with it.

@araselahi
Copy link
Author

@mmalerba with DateAdapter implementation, currently you have done the critical task for calendar logic internationalization. thank you so much for your consideration. I am here to contribute for implementing JalaliDateAdapter. is there any sample like: How to implement a new DateAdapter ?

@mmalerba
Copy link
Contributor

mmalerba commented Sep 18, 2017

@peymanebrahimi has been working on a Jalali adapter #5972 (comment), you may want to consider collaborating with him.

Currently the best documentation is just the JSDoc on the DateAdapter https://github.com/angular/material2/blob/master/src/lib/core/datetime/date-adapter.ts

You can also use the NativeDateAdapter and MomentDateAdapter as example implementations:
https://github.com/angular/material2/blob/master/src/lib/core/datetime/native-date-adapter.ts
https://github.com/angular/material2/blob/master/src/material-moment-adapter/adapter/moment-date-adapter.ts

Sorry it doesn't have better documentation yet... I need to work on that. @araselahi

@tobiasschweizer
Copy link
Contributor

Have you thought of supporting Julian Day Numbers for internal conversions from one calendar format to another? There are already JS libraries around that could possibly be used for the conversions (e.g., http://npmjs.com/package/moonbeams).

I am interested in developing the following features:

  • BCE dates for Gregorian and Julian calendar
  • different precisions: day, month, year

@mmalerba
Copy link
Contributor

@tobiasschweizer choosing a different precision is tracked by #4853, this is something we plan to add

BCE dates and a Julian calendar are not features we plan to add to Angular Material, but they are features that we want enable via a custom DateAdapter. If you're interested in working on these we would love for you to share it with the community. If you encounter any limitations of the DateAdapter that prevent you from accomplishing this, feel free to open issues and we will look into it.

@tobiasschweizer
Copy link
Contributor

@mmalerba
Copy link
Contributor

@tobiasschweizer Yep, that's correct. I've been meaning to write a guide on creating a custom DateAdapter but haven't gotten the time. Those two concrete classes should serve as good examples though.

@mmalerba
Copy link
Contributor

mmalerba commented Dec 1, 2017

Ah I see, I had not heard about Julian Day Number before. In that case I think your proposal sounds reasonable. Would the JDNCalendar then be responsible for reporting things like what the months are in its particular calendar system?

Another thing to consider is the parse and display formats. We allow the user to provide mappings for the formats needed by the datepicker via the MAT_DATE_FORMATS token. It sounds like for your idea you would need to come up with a way to represent the format independent of the calendar system. It's kind of the same problem I was trying to solve when I made these mappings in the first place, you could just map each key to a string of the same name and have each concrete JDNCalendar decide how to represent it itself. If we added more formats to the datepicker at some point you would need to just add those to your implementations as well.

@tobiasschweizer
Copy link
Contributor

tobiasschweizer commented Dec 4, 2017

I really like your design that separates the UI-component (datepicker) from a concrete implementation of a calendar (currently JS Date object and MomentJS) using DateAdapter as the interface through which communication between the UI and the calendar is established.

This abstraction greatly enhances the re-usability of the UI component. However, I also see things that are actually calendar specific like the distinction between BCE and CE dates and only make sense for the Gregorian and the Julian calendar.

Would the JDNCalendar then be responsible for reporting things like what the months are in its particular calendar system?

Yes, JDNCalendar would have to have methods that tell the UI-component everything it needs to know to make the date selection possible for the given calendar (e.g., the Hebrew calendar's months are called differently than the months of the Gregorian and Julian calendar). But this would mean that DateApater would have to be extended for that purpose so that the UI component can ask the implementation of DateApter about it. But there are already methods for that in DateAdapter:

  • getMonthNames()
  • getDayOfWeekNames()

Although we aim to be as generic as possible, the UI component might be limited to calendars that work with a concept of years, months, and days.

Another thing to consider is the parse and display formats.

I think localization and format information has to be provided for each implementation of JDNCalendar.

How shall we proceed? I would like to work on JDNCalendar and support implementations for the Gregorian and Julian calendar for now. Of course, implementations for other calendars may be added too.

I think JDNCalendar can be developed outside Angular Material 2 repo, but we need to decide on the additional methods for DateAdapter, and that will affect existing implementations for Date object and Moment JS.

See my sketch:
design_jdncal

Another thing to keep in mind is the precision. A precision can by expressed using two JDNs (see http://www.knora.org/documentation/manual/rst/knora-ontologies/knora-base.html#datevalue, https://github.com/dhlab-basel/Knora/blob/cc53ef8cd072b7c9c53c7e5b3ab3a92c497b3038/webapi/src/main/scala/org/knora/webapi/util/DateUtilV1.scala). If the two numbers are equal the precision is day. Month precison would be from the first day of the month to the last and the same logic applies to the year. Periods may be expressed by simply having two datepickers, i.e. two dates that might have different precisions.

@tobiasschweizer
Copy link
Contributor

tobiasschweizer commented Dec 5, 2017

I am having a look at the abstract methods of DateAdapter and the ones that are overridden by its subclasses.

I am quite sure I forgot some of the methods or misunderstood some of them, please feel free to correct me ;-)

  1. With date: D as parameter (get information from or modify a date instance):
  • getYear(date: D): number: returns the given date's year as a number (e.g., 2017).
  • getMonth(date: D): number: returns the given date's month, starting with index 0 for January.
  • getDate(date: D): number: returns the index for the day of the month for the given date, starting with 1. Wouldn't it be clearer to use the term "day"?
  • getDayOfWeek(date: D): number returns the index for the day of the week for the given date, starting with 0 for Sunday
  • getYearName(date: D): string: returns the given date's year as a string Isn't that somehow redundant? -> getYear(date: D): number
  • getNumDaysInMonth(date: D): number: returns the number of days for the given date's month.
  • addCalendarYears(date: D, years: number): D: increases the given date by the given amount of years
  • addCalendarMonths(date: D, months: number): D increases the given date by the given amount of months
  • addCalendarDays(date: D, days: number): D: increases the given date by the given amount of days
  • isValid(date: D): boolean: returns true if the given date is valid
  • isDateInstance(obj: any): returns true if obj is of type D (the type of date supported by the implementation of DateAdapter)
  1. Methods needed by the UI component for the given calendar format D (no instance of D required though):
  • getMonthNames(style: 'long' | 'short' | 'narrow'): string[]: returns the names of the months as an ordered list
  • getDateNames(): string[]: returns an ordered list of strings "1" to "31" (regardless of how many days the current date's month has) Wouldn't it be clearer to use the term "day"?
  • getDayOfWeekNames(style: 'long' | 'short'): string[]: returns an ordered list of the names of all days of the week, starting with Sunday
  • getFirstDayOfWeek(): number: returns the index of the first day of the week, i.e. 0 (Sunday)
  1. Methods to construct an instance of a date:
  • clone(date: D): returns a copy of the given date.
  • createDate(year: number, month: number, date: number): D constructs a date Wouldn't it be clearer to use the term "day" for the last parameter?
  • today(): D: returns a date representing today's date
  • parse(value: any, parseFormat: any): D | null: constructs a date from a user provided value, taking into account locales if possible (e.g., for Moment JS)
  • deserialize(value: any): D | null: attempts to construct a date from the provided value
  • invalid(): constructs an invalid date instance
  1. Methods to serialize a date:
  • format(date: D, displayFormat: any): string: serializes the given date to a string, using the given format
  • toIso8601(date: D): string: serializes the given date to a ISO date string

@tobiasschweizer
Copy link
Contributor

tobiasschweizer commented Dec 5, 2017

I think each implementation or subclass of JDNCalendar has to provide an own implementation of the methods in group 2 since these are specific to the calendar format.

For createDate, parse and deserialize as well as today in group 3 an indication of the calendar format is needed. Gregorian could be made the default, so existing implementations wouldn't break.

When serializing the date, the calendar information has to go somewhere (group 4), it could be omitted for Gregorian.

For the year (group 1), BCE dates could be tricky.

@mmalerba
Copy link
Contributor

mmalerba commented Dec 7, 2017

Apologies for the slow response. I agree with what you've outlined above. I think this is a cool idea, it would be great for people who need a more robust solution for dealing with multiple calendars.

Here's some thoughts & rationale for some of the decisions:

But there are already methods for that in DateAdapter:

  • getMonthNames()
  • getDayOfWeekNames()

Although we aim to be as generic as possible, the UI component might be limited to calendars that work with a concept of years, months, and days.

Yes this does limit us to calendars that use years, months, and days. Though I think that should cover the vast majority of calendars people would want to use with the datepicker. Though one of the things I don't like about these various get*Name[s] methods is that they kind of mix date format stuff into the logic. Another idea would be to have method like getNumMonthsInYear(date: D) and getNumDaysInMonth(date: D) we could then get the names of the months by creating a date for the month and doing something like format(date, formats.LONG_MONTH_NAME). Changing the API to this would also allow us to support calendars that have a variable number of months depending on the year .

Wouldn't it be clearer to use the term "day"?

I used "date" to stay consistent with what javascript does and avoid confusion with days of the week. Though I agree its confusing in its own way. I would be ok replacing the "date" APIs with "dayOfMonth".

Isn't that somehow redundant? -> getYear(date: D): number

The idea was that the name variant could be used in situations where the string representation was more than just the number. For example in Japanese maybe someone would want to include the year kanji: "2017年". Though as I mentioned above I don't like how these "-name" APIs mix in formatting logic. It might be better to move to something like format(date, formats.YEAR_NAME).

Do you want to start a repo for it? If you run into flexibility issues with the DateAdapter API as you go let me know and I'll consider making changes. I'd also be happy to review code if you need an extra set of eyes on anything.

@tobiasschweizer
Copy link
Contributor

@mmalerba No worries! Thank you very much for your detailed response.

I have started implementing JDNConvertibleCalendar here: https://github.com/dhlab-basel/JDNConvertibleCalendar. I still need to figure out how to structure it because I want it to become an npm module.

I also still need to figure out how date manipulations work (increasing and decreasing year, month, and day). I have already added some simple conversion tests. The current implementation will still change a lot, but I hope that there will be a proof of concept soon.

I did not bother with precision yet (every date has an exact start and end so far: day precision), also I did not care about string formats yet. I think a lot of this should be handled in the implementation of DateAdapter for JDNConvertibleCalendar. JDNConvertibleCalendar should only handle the conversion logic and the math used for manipulations (jump to the next month or year when increasing days etc.). Since I work at a university, I will get all the scientific support I need.

In which repo would the implementation of DateAdapter have to go for JDNConvertibleCalendar?

@mmalerba
Copy link
Contributor

Hmm I think its up to you how you want to structure it. You could put it in the same repo but make a separate npm package from the core calendar logic if you want to make the calendar logic available to people who aren't using Angular. The angular specific stuff would probably consist of the date adapter, a set of formats, and a module or 2 that people can import to easily set up the providers.

This is similar to what we do for the MomentDateAdapter it lives in the same repo as the rest of material, but we publish it as its own npm package since it has additional dependencies.

@tobiasschweizer
Copy link
Contributor

I think it would make sense to put the JDNConvertibleCalendarDateAdapter in the Angular Material 2 repo. https://github.com/dhlab-basel/JDNConvertibleCalendar could still be used without Angular Material 2. Also if DateAdapter is going to be changed in the future, this would make things easier to coordinate.

I forked the Angular Material 2 repo. Shall I implement JDNConvertibleCalendarDateAdapter there and create a PR? I might have some questions how to include it in app-module.ts in our Angular app https://github.com/dhlab-basel/Salsah.

How shall I deal with the DateAdapter interface? Shall I just add what I think is needed as proposed in #2519 (comment)?

Maybe it would make things easier if we could talk briefly. However, I suppose your are located in the US and I am here in Europe (time diff.).

@tobiasschweizer
Copy link
Contributor

@mmalerba I created a new branch on my forked repo from angular/material2: https://github.com/dhlab-basel/material2/tree/datepicker-datadapter-jdnconvcal

I am struggling with package.json and the basic structure (index.ts, tsconfig). I would be glad if you could give me a hand here. I guess once I have the basic setup similar to src/material-moment-adapter I should be fine and can implement it by myself.

@mmalerba
Copy link
Contributor

@tobiasschweizer I can set up some time to do a Hangouts conversation if you like. Shoot me an email: mmalerba@google.com

@tobiasschweizer
Copy link
Contributor

@mmalerba As soon as a build with our merged PR #9639 is available, I will make a proof of concept in my repo https://github.com/dhlab-basel/JDNConvertibleCalendarDateAdapter with a custom header so that the user can switch between Gregorian and Julian calendar formats. https://github.com/dhlab-basel/JDNConvertibleCalendar will have to be extended too so that more calendar formats are supported in the future.

@tobiasschweizer
Copy link
Contributor

tobiasschweizer commented Mar 24, 2018

I think it is already there angular/material-builds@d6e71c9

@tobiasschweizer
Copy link
Contributor

@mmalerba @araselahi

We added support for the Islamic calendar.

See https://stackblitz.com/edit/angular-qapxhn

I set the locale to 'ar', 'en' is used as a fallback for the names of weekdays and months. I think there is still a RTL issue:

Islamic_Date

Also abbreviations would be nice for transliterations of the Arabic names, see https://github.com/dhlab-basel/JDNConvertibleCalendar/blob/master/src/names.json

Could you give me a hand here?

@tobiasschweizer
Copy link
Contributor

btw: all the available calendars can also be used individually. In the date adapter, I still have to figure out a way to set the initial calendar correctly, see dhlab-basel/JDNConvertibleCalendarDateAdapter#9

@jelbourn
Copy link
Member

(revisiting old feature requests)

Closing this issue since I don't realistically ever see us prioritizing adding support for non-Gregorian calendars. With the current state of our backlog, it would be years before we would even consider this, and I don't foresee it ever getting near the top of the queue.

@tobiasschweizer
Copy link
Contributor

(revisiting old feature requests)

Closing this issue since I don't realistically ever see us prioritizing adding support for non-Gregorian calendars. With the current state of our backlog, it would be years before we would even consider this, and I don't foresee it ever getting near the top of the queue.

I understand.

Could you tell me anything about the priority of the precision task (year or month selection)? At the moment, the date and range pickers only allow for day selection.

@jelbourn
Copy link
Member

@tobiasschweizer it's something I'd like to explore eventually, but I don't see us dedicating any time to it in 2021

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Feb 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: material/datepicker feature This issue represents a new feature or feature request rather than a bug or bug fix help wanted The team would appreciate a PR from the community to address this issue needs: discussion Further discussion with the team is needed before proceeding P5 The team acknowledges the request but does not plan to address it, it remains open for discussion
Projects
None yet
Development

No branches or pull requests

7 participants