js-temporal / temporal-polyfill

Polyfill for Temporal (under construction)
ISC License
529 stars 28 forks source link

BUG: `dayOfWeek` is always same in different calendars #208

Closed tounsoo closed 1 year ago

tounsoo commented 1 year ago

Jan 1, 2023 in iso8601 Calendar

Expectation: Since iso8601 calendar's week starts on a Monday, dayofweek should be 7

image

Jan 1, 2023 in Gregory Calendar Expectation: Since Gregory calendar's week starts on a Sunday, dayofweek should be 1

image
ptomato commented 1 year ago

It's not correct that the Gregorian calendar's week starts on a Sunday ­— this is locale-dependent. The value of dayOfWeek isn't intended to be locale-dependent, so Monday is still 1 and Sunday is still 7 in the Gregorian calendar.

tounsoo commented 1 year ago

Gotcha, in that case, what option would make it so that Sunday is 1?

Edit: I'm trying to use this to render a calendar component and would make my life so much easier if this was provided somehow by the locale or an option.

ptomato commented 1 year ago

Unicode locale codes have an extension key to indicate the first day of the week, however this isn't currently specified to be part of Intl or supported in any JavaScript engine. Nor is there currently a locale-dependent option to format the day of the week as a number. So it would have to be an option in your component.

You could do something like this: (assuming options.fw is 'mon' or whatever)

const daysOfWeek = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
function localeSensitiveGregorianDayOfWeek(options, plainDate) {
  if (plainDate.calendar.id !== 'gregory')
    throw new Error('this function is intended for calendar = gregory');
  const adjustment = daysOfWeek.indexOf(options.fw);
  const mondayBasedDayOfWeek = plainDate.dayOfWeek;
  return (mondayBasedDayOfWeek - 1 - adjustment) % 7 + 1;
}

and use that instead of the value of dayOfWeek directly. (note, not tested very much; also plainDate.calendar.id will likely be replaced by plainDate.calendarId before the proposal reaches stage 4)

tounsoo commented 1 year ago

If the start day is different depending on the locale instead of the calendar, I assume providing the locale should change that automatically to match what that locale expects? Hmm..

ptomato commented 1 year ago

The thing is that:

If there were a locale-dependent API to format the day of the week as a number, that took the locale first-day-of-week setting into account, it might look something like this:

plainDate.toLocaleString("en-ca-u-fw-sun", { weekday: "numeric" })  // "1"?
plainDate.toLocaleString("en-ca-u-fw-mon", { weekday: "numeric" })  // "7"?

But that doesn't exist, so you have to write your own.

tounsoo commented 1 year ago

Gotcha. I do think it would be nice if it was part of Intl so that we don't have to manually figure it out. Thank you for all the help, I'll close this :D