Calendar / datepicker with non Gregorian date locale

Hi @nolimits4web,

I have been trying to use datepicker with a non-Gregorian locale, ‘fa-IR’ for hours. The locale is supported by Intl.DateTimeFormat. There are, however, some sever problems preventing the use of calendar.

When you pick a year or month using pickers, you may see the month or year with an offset of 1 be selected. For example, I am born 1978/06/22 which translates to 1357/04/01 (YYYY/MM/DD). If I select year 1357 from the year picker, 1356 is shown instead. I correct it to 1357 using the ‘<’ control. Now, if I pick the month ‘تیر’ (which is 4th one), the calendar shown is for next month! If I click the ‘>’ control for the month, it displays the correct calendar.

I believe that the problem is the shift between the two systems which can cause problems. I know that it may not be easy to debug such a problem when you do not know the Jalali calendar, so I am more than happy to help. I also remember that there was a ‘jalali’ object in the previous versions (which had the same problems; see the forum).

I went further and debugged the code. Below you can find one of my test files.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calendar test</title>
</head>

<body>
  <div id="app">
    <div class="view view-main view-init">
      <div class="page">
        <div class="page-content">
          <button onclick="test();">Test</button>
        </div>
      </div>
    </div>
  </div>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/framework7/5.5.1/css/framework7.bundle.rtl.css">
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/framework7/5.5.1/js/framework7.bundle.js">
  </script>
  <script type="text/javascript">
    app = new Framework7({
      root: '#app'
    });

    function test() {
      c = app.calendar.create({
        locale: 'fa-IR',
        on: {
          dayClick: function (calendar, dayEl, year, month, day) {
            alert('Picked ' + year + '/' + (month + 1) + '/' + day + ' :: ' + new Intl.DateTimeFormat('fa-IR')
              .format(new Date(year, month, day)));
            calendar.close();
          }
        }
      });
      c.renderYearPicker = function () {
        const calendar = this;
        const currentYear = calendar.currentYear;
        let yearMin = calendar.params.yearPickerMin || new Date().getFullYear() - 100;
        if (calendar.params.minDate) {
          yearMin = Math.max(yearMin, new Date(calendar.params.minDate).getFullYear());
        }
        let yearMax = calendar.params.yearPickerMax || new Date().getFullYear() + 100;
        if (calendar.params.maxDate) {
          yearMax = Math.min(yearMax, new Date(calendar.params.maxDate).getFullYear());
        }
        const years = [];
        for (let i = yearMin; i <= yearMax; i += 1) {
          years.push(i);
        }
        return `
                <div class="calendar-year-picker">
                    ${years.map(year => `
                    <div data-year="${year}" class="calendar-year-picker-item ${year === currentYear ? 'calendar-year-picker-item-current' : ''}">
                        <span>${calendar.yearFormatter.format(new Date(year, calendar.currentMonth))}</span>
                    </div>
                    `).join('')}
                </div>
                `;
      };
      c.sym = c.setYearMonth;
      c.setYearMonth = function (year, month, transition) {
        alert('year: ' + year + ', month: ' + month);
        this.sym(year, month, transition);
      }
      c.open();
    }
  </script>
</body>

</html>

First, by changing the renderYearPicker method, I fixed the issue of (sometimes) selecting a wrong year. But after more testing, it seems that there is bigger problem in onMonthSelectorItemClick. When I select the month, it calls setYearMonth with a negative month! You can see that in the provided code.

Could you please take a look at it and see if it can be fixed with a minor effort, or I have to rewrite all ‘render’ functions from scratch. I can provide you with conversion routines available freely on the web as well as any information.

Thanks!

Fiddle: https://jsfiddle.net/a0yg9Lqj
Digit mapping: ‘0123456789’ = ‘۰۱۲۳۴۵۶۷۸۹۰’

Maybe you can help with source code at https://github.com/framework7io/framework7/blob/master/src/core/components/calendar/calendar-class.js ? For me it is really complex to debug this thing :slight_smile:

1 Like

Indeed I was looking at a local copy of that. It is not easy for me either, but I will do my best!

Thanks, feel free to ask if you can’t find something there!

1 Like

Vladimir, as my project has a hard deadline in few days, I decided to solve the problem without a datepicker (well, a simple one using three drop downs). But, can you tell me what does this line mean? I think this is absolutely a problem; look at the 3rd argument (negative) as well as the logic:

At MDN, I see no negative arguments are allowed to Date() constructor.

Thank you!

I found this https://stackoverflow.com/a/41345095

1 Like

you can use moment-jalaali for the jalaali calendar system

i was reading the calendar-class.js and for example in the renderMonth method you can definitely use moment-jalaali methods to get day, month and year if the locale is of jalaali system.

methods like moment().jMonth() | moment().jDay() | moment().jYear() and …

im a noob , i struggle to understand the source code of calendar-class.js but like i said im a noob

Thanks Milad for your reply!