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

feat: ethiopic calendar #2658

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

feat: ethiopic calendar #2658

wants to merge 4 commits into from

Conversation

gpbl
Copy link
Owner

@gpbl gpbl commented Jan 7, 2025

This PR introduces support for the Ethiopic calendar in the DayPicker.

The PR is still a work in progress. Switch to this branch to start applying changes to the source.

How It Works

The Ethiopic calendar is rendered by importing it from react-day-picker/ethiopic, similar to how we handle the Persian calendar.

import { DayPicker } from 'react-day-picker/ethiopic';

<DayPicker />
  • Understand the correct name, Ethiopian or Ethiopic? "Ethiopic" is correct.

Ethiopic Module

  • src/ethiopic/index.tsx: render DayPicker using the Ethiopic calendar, including the overridden locale and numeral system props.
  • src/ethiopic/lib: module to contain the date-fns functions to override for date calculations and formatting (see below).

Example Component and Docs

  • examples/Ethiopic.tsx: the example components.
  • examples/Ethiopic.test.tsx: test file for the new Ethiopic calendar example.
  • website/docs/docs/localization.mdx: add Ethiopic Calendar paragraph.
  • website/components/playground: add Ethiopic Calendar option.

See Working With the Source Code to start the examples app and reach http://localhost:5173/?example=Ethiopic to see it running.

Numeral System and Locale

  • Understand which locale should be used. Are they included in date-fns already?
  • Understand which numeral systems we need to support.
  • src/types/props.ts, src/types/shared.ts: include the Ethiopic numeral system.
  • Update DateLib to work with the new numeral system (e.g., getDigitMap).

Ethiopic DateLib

Having the Ethiopic date library compatible with the DateLib overrides protocol is the most challenging part of this project. The DateLib is initialized here with the Ethiopic overrides and should work out-of-the-box once we provide the correct functions.

In the absence of a package like date-fns-ethiopic, we can initially include the Ethiopic DateLib override functions in the DayPicker package. Note that not all functions may require an Ethiopic version.

  • Complete the missing functions (see list below) and their tests.
List of DateLib functions
  • addDays
  • addMonths
  • addWeeks
  • addYears
  • differenceInCalendarDays
  • differenceInCalendarMonths
  • eachMonthOfInterval
  • endOfBroadcastWeek
  • endOfISOWeek
  • endOfMonth
  • endOfWeek
  • endOfYear
  • format
  • formatNumber
  • getISOWeek
  • getMonth
  • getWeek
  • getYear
  • isAfter
  • isBefore
  • isSameDay
  • isSameMonth
  • isSameYear
  • max
  • min
  • newDate
  • setMonth
  • setYear
  • startOfBroadcastWeek
  • startOfDay
  • startOfISOWeek
  • startOfMonth
  • startOfWeek
  • startOfYear
  • today

Configuration and Build

  • package.json: includes the Ethiopic calendar module.
  • ethiopic.js: added module export for the Ethiopic calendar.
  • Verify the type export with https://arethetypeswrong.github.io

@@ -0,0 +1,4 @@
/* eslint-disable @typescript-eslint/no-require-imports */
/* eslint-disable no-undef */
const ethiopic = require("./dist/cjs/ethiopic/index.js");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the todo "Understand the correct name, Ethiopian or Ethiopic?".
From what I searched online:

... “Ethiopic” can be used more broadly to describe anything related to Ethiopia, though it is less common in this usage compared to “Ethiopian".

IMO even if "Ethiopic" is technically more correct, using "Ethiopian" seems better because it results in better discoverability, due to it being more used.
The discoverability is also better even if someone searches for "Ethiopia", because the search would still match with the "Ethiopian" word.

Copy link
Owner Author

@gpbl gpbl Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting thanks for looking it up.

I actually renamed it to "ethiopic" because this is the name in Mac OS Settings (I use the MacOS calendar as reference):

Screenshot 2025-01-07 at 9 14 39 AM

A recommendation I got from ChatGPT is:

  • Use Ethiopian calendar for general references or modern discussions.
  • Use Ethiopic calendar when emphasizing the historical, cultural, or technical aspects of the calendar.

Also, the numerals... "The Ethiopian calendar traditionally uses the Ethiopic numerals as its default numeral system."

Not sure what is the best here, maybe @temesgen-mulugeta has a better idea...

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: @temesgen-mulugeta agrees with Ethiopic:

Thinking about the name, I think "Ethiopic" is better. It pays homage to the Geez language, which is the basis of the calendar.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the insights!
That is a good point to follow existing conventions, like Mac OS, and also ask other people who have more context.

@temesgen-mulugeta
Copy link

  • Thinking about the name, I think "Ethiopic" is better. It pays homage to the Geez language, which is the basis of the calendar.

  • When it comes to the numerals. There are specific geez numerals, so I can also work on that and add them to the utility functions, and we can add the support for it.

  • I have implemented most of the date-fns functions that need to be overridden in my repo. But I haven't written tests for it, and I can also assist with that. From my experience, overriding the months and years functions is enough, with the exception of getWeek to get the week count right.
    https://github.com/temesgen-mulugeta/shadcn-ethiopian-date-picker/blob/main/src/lib/EthiopianDateLib.tsx

@gpbl
Copy link
Owner Author

gpbl commented Jan 7, 2025

  • I have implemented most of the date-fns functions that need to be overridden in my repo. But I haven't written tests for it, and I can also assist with that. From my experience, overriding the months and years functions is enough, with the exception of getWeek to get the week count right.

That's wonderful, thanks! Based on your work there, would it be possible to code pure functions that we can unit test, a-la date-fns style?

  • Their names and signatures must match those in http://daypicker.dev/api/classes/DateLib.
  • I expect these functions to populate the /src/ethiopian/lib directory. See, for example, the startOfYear I added as an example in this PR.

From the "List of DateLib functions," which ones do you know for sure we have to add, and which ones can we just ignore?

  • addDays
  • addMonths
  • addWeeks
  • addYears
  • differenceInCalendarDays
  • differenceInCalendarMonths
  • eachMonthOfInterval
  • endOfBroadcastWeek
  • endOfISOWeek
  • endOfMonth
  • endOfWeek
  • endOfYear
  • format
  • formatNumber
  • getISOWeek
  • getMonth
  • getWeek
  • getYear
  • isAfter
  • isBefore
  • isSameDay
  • isSameMonth
  • isSameYear
  • max
  • min
  • newDate
  • setMonth
  • setYear
  • startOfBroadcastWeek
  • startOfDay
  • startOfISOWeek
  • startOfMonth
  • startOfWeek
  • startOfYear
  • today

@gpbl
Copy link
Owner Author

gpbl commented Jan 7, 2025

When it comes to the numerals. There are specific geez numerals, so I can also work on that and add them to the utility functions, and we can add the support for it.

Interesting. Which numerals should we support?

In my implementation, I could rely on Intl native object to switch to other numerals:

private getDigitMap(): Record<string, string> {
const { numerals = "latn" } = this.options;
// Use Intl.NumberFormat to create a formatter with the specified numbering system
const formatter = new Intl.NumberFormat("en-US", {
numberingSystem: numerals
});
// Map Arabic digits (0-9) to the target numerals
const digitMap: Record<string, string> = {};
for (let i = 0; i < 10; i++) {
digitMap[i.toString()] = formatter.format(i);
}
return digitMap;
}

Are all the numerals used in the Ethiopic calendar included in the Intl object? In MacOS, they list two calendars: Ethiopic and Ethiopic (Alete Alem). Is Geʽez another one? 🤔

@temesgen-mulugeta
Copy link

From the "List of DateLib functions," which ones do you know for sure we have to add, and which ones can we just ignore?

From my experience, I’ve identified these as essential practices, and I’ve already implemented them. I will convert them into pure functions and incorporate unit tests for the functions.

  • addMonths
  • addYears
  • differenceInCalendarMonths
  • endOfMonth
  • endOfYear
  • format
  • formatNumber
  • getMonth
  • getWeek
  • getYear
  • isSameMonth
  • isSameYear
  • newDate
  • setYear
  • startOfMonth
  • startOfYear

@temesgen-mulugeta
Copy link

Interesting. Which numerals should we support?

The only numeral we should consider is Geez. The numerals look like '፩', '፪', '፫', '፬'. But I don't think we have support for it on Intl. But the numerals shouldn't be the primary focus. Since most of us use Western Arabic numerals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants