Closed glittle closed 4 years ago
@glittle I'll try to look at that maybe in 2 weeks and so. just quick note, this calendar wouldn't be used in formatting dates. the reason is it is not associated with any culture and this has to be supported by the OS. i.e. Windows need to support it and ICU library on Linux will need to support it.
Also, could you talk more about if you are going to provide your implementation or will you pick the implementation from some other place? This is important to know because of the code licensing. I prefer we use our own implementation as I am seeing it is a simple calendar which easily can be implemented. anyway, I'll try to look at the details of the calendar and find out what is the best option to implement it.
Thanks for providing the proposal.
@tarekgh Issue is updated as requested...
A few thoughts on the API:
It turns out that to compute the correct date on the Badí calendar, one also needs a latitude/longitude location. That's because what day it is depends on whether or not the sun has set, and that varies both by latitude and longitude even if the time zone is fixed. Still most of the astronomical calculations can be pre-computed (e.g. what day Naw-Ruz lands on), and the only thing that might need to be computed dynamically is the time of sunset for a given location. Perhaps the latitude/longitude may be supplied in the constructor. Perhaps there should also be a default value, but it's not clear to me what that should be.
It's worth putting careful thought into where the precomputed dates come from. The Universal House of Justice used dates provided by Her Majesty's Nautical Almanac Office in the United Kingdom. I know that trying to compute the dates with off-the-shelf algorithms can be tricky, because the difference between the Spring equinox and the time of sunset in Tehran can be smaller than the typical approximation errors of these algorithms (and in fact, if you use the algorithms provided in Meeus, it gets at least one date wrong in the near future; see https://github.com/bchurchill/badi-cal/blob/master/src/Astronomy.js#L114). This question probably doesn't need to be answered right away, but it's worth thinking about.
For Ayyam-i-Há, I think the reason the design choice seems tricky is because of the challenge of mapping the month names to integers. However, I would suggest that mapping month names to integers (or floats) isn't what the API would be used for. That said, I can imagine wanting to perform comparisons (less-than, greater-than, etc.) on the results of GetMonth(). Maybe therefore an enumeration or a special class with overloaded comparison operators would be suitable for this.
I'd also suggest creating a class to represent Badí dates, rather than using a tuple of integers. This would also help with the Ayyam-i-Há issue, because it would help hide the implementation details from the user. The class to represent Badí dates may be equipped with methods to output formatted text, convert back to a DateTime object, etc. The Badi date would then have methods to get the day of the month, the month of the year, and could even have a method to query whether or not the date lands during Ayyam-i-Há.
Can you provide a reference to these "four elements"? I haven't heard of this in reference to the Badí calendar before.
Thanks, @bchurchill for those five comments. I'll respond to each...
1) Yes, the days do start at sunset, but that is beyond the scope of most generic systems. For this implementation, as with the other calendars that also start the day at sunset, the time is ignored and the date for the main part of the day is used. For a complete system, you would want to know whether sunset has occurred or not. If it has, this is the "eve" of the following daytime so use the date for "tomorrow". Maybe this could be a part of the proposed support package.
2) Agreed. The table of dates is important. For now, I consider the currently available list to be the most dependable for the next few hundred years.
3) To keep it simple, I'm liking the "Option 2" of the proposal where the user of the system can use whichever model is appropriate for the current situation.
4) Sounds good. That could be built up in a support package leveraging the base system. The function to determine whether a date is in Ayyam-i-Ha is a good one... I'll add that to the proposal.
5) The Báb, who first defined the Badíʿ calendar wrote this: "The first three months are the fire of God, the next four months, the air of eternity, and the subsequent six months are the water of divine unity which streameth forth upon all souls, descending from the atmosphere of eternity, which in turn is derived from the fire of God. The last six months pertain to earthly existence, whereby all that hath appeared from these three elements may be established within the element of dust, through which the fruit will be harvested." (source)
@bchurchill regarding your point "It's worth putting careful thought into where the precomputed dates come from.": I'm the creator of https://github.com/janrg/badiDate and I've looked at this question in quite some depth. There are multiple sources of error that can lead to discrepancy, with the dominating one for far future dates being ΔT, the error on which will reach several minutes just over the next few hundred years (. I did a detailed error analysis and found the first problematic year to be 509 B.E. (2352 AD) since the difference the northward equinox and the nearest sunset is only 9 minutes, which is only 1.5 times the estimated error on ΔT. There are two other instances of close calls before then, but they both fall into the range of dates included in the list (the main one being in 2026 AD which you have already pointed out, where the difference is only about 22 seconds ) and it is thus easy to make sure that they come out correctly. I think the range of dates should be limited to 507 B.E. inclusive (since with Naw-Rúz 509 B.E. uncertain, we can only be sure of dates up to 4 Ayyam-i-Há 508 B.E.) as I have done with my library and I would be very happy to provide the pre-computed list of dates (see e.g. https://github.com/janrg/badiDate/blob/master/res/badiYearsLongFormat.js). It's worth pointing out that the Universal House of Justice has asked me to make it clear with regards to my library that dates beyond the range covered in the published list are not authoritative, so a statement to that effect should be included in the documentation.
@glittle thanks for the proposal, here are some comments and questions I hope you can help with:
public partial class BadiCalendar : System.Globalization.Calendar
{
public static readonly int BadiEra; // always return 1 as we have just one era
public BadiCalendar() { }
public override System.DateTime MaxSupportedDateTime { get { throw null; } }
public override System.DateTime MinSupportedDateTime { get { throw null; } }
public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } } // This should return CalendarAlgorithmType.SolarCalendar
public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
public override int GetDayOfMonth(System.DateTime time) { throw null; }
public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
public override int GetDayOfYear(System.DateTime time) { throw null; }
public override int GetDaysInMonth(int year, int month, int era) { throw null; }
public override int GetDaysInYear(int year, int era) { throw null; }
public override int GetEra(System.DateTime time) { throw null; } // always return 1 after validating the input DateTime
public override int GetMonth(System.DateTime time) { throw null; } // I'll talk more about this one below
public override int GetMonthsInYear(int year, int era) { throw null; }
public override int GetYear(System.DateTime time) { throw null; } // the returned year is absolute value and not the year number in the Vahid or Kull-i-Shay cycles
public override int[] Eras { get { throw null; } } // return new int [] { 1 }
public override bool IsLeapDay(int year, int month, int day, int era) { throw null; } // we need to decide if this return true in the last day of the Ayyam-i-Ha in the leap years?
public override int GetLeapMonth(int year, int era) { throw null; } // We need to decide about the behavior of this one depending on what we do on GetMonth().
public override bool IsLeapMonth(int year, int month, int era) { throw null; }
public override bool IsLeapYear(int year, int era) { throw null; }
public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
public override int TwoDigitYearMax { get { throw null; } set { } }
public override int ToFourDigitYear(int year) { throw null; }
}
For GetMonth method, the suggestion to have GetMonth return a floating point number is not going to work because we override the base class one which returns integer. I would suggest we return 0 for Ayyam-i-Ha period and we document the behavior. and in GetLeapMonth we'll return 0 if the Ayyam-i-Ha ha month has 5 days, otherwise we'll return -1. the other idea could be, we'll assign the month number 20 to the Ayyam-i-Ha and let GetLeapMonth return either 0 if it is 4 days and 20 if it is 5 days.
For the methods:
GetYearOfVahid(DateTime) - Number from 1 to 19.
GetVahid(DateTime) - Number from 1 to 19.
GetKullishay(DateTime) - Number from 1.
IsInAyyamiHa(DateTime) - bool. True when the date is in Ayyam-i-Ha.
I would suggest instead to have the following methods:
public System.DateTime ToDateTime(int kulliShay, int vahid, int year, int month, int day) { throw null; } // not that the year is from 1 ~ 19 plus the Ayyam-i-Ha period number (0 or 20 depending on what we decide on the previous bullet)
public void ToBadiDate(DateTime time, out int kulliShay, out int vahid, out int year, out int month, out int day) {}
Let's resolve the opened issues here and then we can update the proposal and move forward. Thanks again for looking at that.
@glittle any news here?
Thanks, @tarekgh! Some responses in a couple of comments...
Fortunately, there is only one definition of the Badíʿ calendar and it is purely astronomical. We are currently in year 175 B.E. Before 172 (three years ago) the calendar was not fully defined and the common practice was to start the year on March 21. However, from the start of 172 and into the future, the year is started on the day (between sunsets) in Tehran, Iran that contains the vernal equinox. The authority behind the Badíʿ calendar is the Universal House of Justice, and here is their letter announcing this detail. Dates before the start of the Era are not defined.
As you can imagine, projecting that calculation into the future is quite complex. They followed up with a listing of dates for the next 50 years. The "Equinox" sections of the 2nd and 3rd FAQs on this page describes some of the complexity of doing the calculations! @janrg also describes this in a comment above.
So, I'd highly recommend that we simply embed a table of results (about 500 bits). The original calculation of the dates should not be the responsibility of this system. This was done in NodaTime but, as @janrg has pointed out, we can use a shorter list, up to year 507.
For the exact list of functions in the API, I'll defer to your knowledge of the current system and what is required. However, here are some questions...
AlgorithmType
? There will only be one, so I'm not sure we need this.GetDaysInMonth
may not be needed, or can simply return 19.GetMonthsInYear
is not needed, or can simply return 19.Calendar
has these functions and we need to override them, I'd prefer to throw a InvalidOperationException
exception rather than trying to give them some contrived meaning. The idea of a "leap" day or year is to realign a calendar with the astronomical reality. The Badíʿ calendar is astronomical by definition, so never gets out of sync!GetMonth
, I agree that it should return 0 for Ayyam-i-Ha. I would still like to make a parallel function, such as GetMonthSortable
that returns 18.5 for Ayyam-i-Ha.ToBadiDate
function seems reasonable and would eliminate the need for the extra getters.ToString
function? I would expect that people will want to develop something similar to CalendarUtility
specifically for the Badíʿ calendar.They followed up with a listing of dates for the next 50 years.
Does the Universal House of Justice is the publisher of this data? or someone else?
As you can imagine, projecting that calculation into the future is quite complex.
This is not a big problem as we already doing similar idea in the Persian calendar. I mean in the Persian calendar we calculate the astronomical event there too. I believe we can calculate it for the Badi calendar too. the Calendrical Calculation book has the details on how to calculate it and it is not that complex. The catch here, according to the astronomical calculations the year 2096, the vernal equinox will have the calendar year start on March 19 according to Tehran coordinates. I know this year is not published in the 50 years list but do we have any source what would be the start of the Naw-Ruz on 2096?
So, I'd highly recommend that we simply embed a table of results (about 500 bits).
We can carry the confirmed dates. I am worried about the non-confirmed dates. how did you get the data beyond the 50 years in the list? did you calculate it yourself? or got it from some other source? who confirmed the correctness of this data?
In the main code listing above, there are no functions that don't override a base function. Are we allowed to introduce functions that are specific to this calendar?
Yes, we allowed adding more specific methods to the Badi calendar. we already do that with other calendars.
What is the purpose of AlgorithmType? There will only be one, so I'm not sure we need this.
We have to have this. this is telling the type of the calendar (i.e. Solar, Lunar or Lunisolar). anyone using calendar object (not necessary know this is the Badi calendar) can check blindly if the calendar is solar or another type. we should have this.
GetDaysInMonth may not be needed, or can simply return 19.
This method is an abstract method in the base Calendar class which requires every calendar to implement. Also, note that, if we are going to have a specific number to the Ayyam-i-ha then GetDaysInMonth will return 4 or 5 for that.
GetMonthsInYear is not needed, or can simply return 19.
Same answer as the last question.
There is no concept of LeapDay or LeapYear in the calendar. The closest analogy is the number of days in Ayyam-i-Ha (which is usually 4 or 5, but could possibly be 3). I would remove all the "Leap" functions. If the base Calendar has these functions and we need to override them, I'd prefer to throw a InvalidOperationException exception rather than trying to give them some contrived meaning. The idea of a "leap" day or year is to realign a calendar with the astronomical reality. The Badíʿ calendar is astronomical by definition, so never gets out of sync!
We cannot throw an exception here. imagine a library written to work with any calendar and it getting a calendar object as input. if we throw an exception, the library has to special case working with Badi because it'll throw while other calendars don't throw. I suggest implementing this as if we have Ayyam-i-ha has 5 days, IsLeapYear will return true. and IsLeapDay will return true only if using Ayyam-i-ha day 5.
There is no need for "TwoDigit" or "FourDigit" year functions. Currently the year is 3 digits, and we have 800 years to worry about a 4th digit and I suspect the .NET framework will go through some updates during that time! :)
The base class is providing the default implementation so we don't have to override it but at least we should check the default implementation is reasonable.
For the GetMonth, I agree that it should return 0 for Ayyam-i-Ha.
Good
I would still like to make a parallel function, such as GetMonthSortable that returns 18.5 for Ayyam-i-Ha.
The concern with that is other APIs that takes month number will not accept this value. what about we define a const in the class for the Ayyam-i-ha something like:
public const int AyyamiHaMonthNumber = 0;
by doing that, the user of this calendar can know what we are returning for this period. having GetMonthSortable is not really going to help in anything because users will need to check for the 0 anyway before using 18.5 which they can do without exposing GetMonthSortable anyway.
I agree that a ToBadiDate function seems reasonable and would eliminate the need for the extra getters.
I am glad you liked the idea
Do we also need to override the ToString function? I would expect that people will want to develop something similar to CalendarUtility specifically for the Badíʿ calendar.
Usually, we don't do that with the calendars. without overriding ToString, the calendar will return System.Globalization.BadiCalendar which is good enough.
could you please update the proposal according to our latest discussion here and I assume the only open issue here is should we fully depend on the data you have or we should use part of it and use the calculation similar to what we did for PersianCalendar https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Globalization/CalendricalCalculationsHelper.cs#L390 which we can calculate the vernal equinox through the astronomical calculation.
to be clear, if we have reliable data we can use it too.
Thank you for your folow up.
we'll return IsLeapYear will return true. and IsLeapDay will return true only if using Ayyam-i-ha day 5.
Sounds good.
users will need to check for the 0 anyway before using 18.5 which they can do without exposing GetMonthSortable anyway
I'm not understanding why this would be. However, since a sorted group of dates would put the Ayyam-i-Ha days in the correct position, I'm not sure that GetMonthSortable would be needed. I'm okay to drop that, and just have GetMonth return 0 for Ayyam-i-Ha dates.
I'll let @janrg comment the calculations as he has more domain knowledge of that!
@janrg please advise with the following:
We can carry the confirmed dates. I am worried about the non-confirmed dates. how did you get the data beyond the 50 years in the list? did you calculate it yourself? or got it from some other source? who confirmed the correctness of this data?
Please have a look at my comment here: https://github.com/dotnet/corefx/issues/30207#issuecomment-396700713 Within the noted period, there are a few years where sunset in Tehran and the equinox come reasonably close, but even the closest approach has a difference of 728 seconds with an uncertainty in delta T (which is the dominating source of uncertainty in all of this) of 131 seconds so I am very confident about the accuracy of these dates. Sunset times are calculated with my library https://github.com/janrg/MeeusSunMoon which implements some of Jean Meeus' Astronomical algorithms, but they pretty much don't change anyway, since such drift is compensated for by insertion of leap seconds. Equinox times are calculated with algorithms written by Jay Tanner (http://neoprogrammics.com/), until 2200 AD using the JPL DE405 model, for later dates using VSOP87.
@tarekgh Ah, we posted at the same time :-)
@janrg I am not clear what is your suggestion here? should we go with the data that @glittle has? or should we use your data? or should we use the astronomical calculation? or we use a mix between using the date and using the calculations?
@tarekgh As far as I know, my data is the most accurate anyone has produced to date. Calculating on the fly is not feasible since accurate equinox calculations are so involved, that it would be a significant performance issue (around 1sec/data point in the PHP implementation I used). My suggestion is to use my data up to 507 BE with a note that dates beyond 221 BE are not authoritative.
The data could also in principle be stored extremely concisely, since the only possible dates for Naw-Rúz in that range are 19, 20, 21, 22, so two bits/year would be enough, 3 if we also want to include the length of Ayyám-i-Há to avoid having to look up next year's date to check that.
Thanks @janrg this is very useful.
As mentioned I have been asked by the Universal House of Justice to make it clear with the data I have produced that only dates covered in the list are authoritative, so this should be stated somewhere in the documentation
does the Universal House of Justice officially approved your data?
In general, I wouldn't mind using your data. do you think we can try to generate the same data with other sources just to validate if your calculation used to generate the data is accurate enough?
Also, do you know if Universal House of Justice accept the years can start on 19th and 22th of March? I am asking as I thought the calendar was designed to have the year starts on 20 or 21 of March but I am not sure if this is true.
regarding the data, I prefer we carry the start of year bits only as Ayyam-i-Ha is easy enough to calculate and the perf wouldn't be an issue too.
No they have not officially approved the data, otherwise it would be authoritative and we wouldn't need a notice in the documentation :-)
Regarding checking the data I spent weeks looking for the most accurate equinox calculations possible so I doubt I'll find anything more or even as accurate, but I'd be happy to check - say - all dates where the "safety margin" (the time between sunset in Tehran and the northward equinox) is less than 10 minutes against some other sources.
The calendar was designed to start on the day on which the equinox falls. The location for determining the date was set to Tehran by a decision of the Universal House of Justice as this was the birthplace of Bahá'u'lláh. But binding it to the equinox comes directly from the Bahá'í Holy Writings. It was just before the full implementation that occurred in 172 BE that the Badí' year was coupled to the Gregorian year and hence always started on 21 March (technically sunset of the 20th).
If you specify to me exactly how you want the data, I'll prepare a list encoding the Naw-Rúz dates 172 to 508 BE.
do you know if Universal House of Justice accept the years can start on 19th and 22th of March?
The Badíʿ calendar is not dependent in any way on the Gregorian calendar, so it isn't concerned with the date in March. The only reason we think about that is that most computers have the Gregorian calendar built-in and we can simply convert dates from Gregorian to Badíʿ.
I prefer we carry the start of year bits only as Ayyam-i-Ha is easy enough to calculate and the perf wouldn't be an issue too.
I'd recommend adding another few bytes of pre-calculated data rather than having to calculate it frequently. That calculation would have to count the days between the start of each year, then adjust if there was a Gregorian leap year in there or not. When doing a listing over a number of years, the calcs would add up.
When doing a listing over a number of years, the calcs would add up.
This is true for most of the calendars so I am not really worried about the perf here. Just to give some idea regarding why I am trying to not have data is because of the size. this calendar will be implemented inside the core (as we do with other calendars) and we have Alpine docker image which we are squeezing the size of the framework as much as we can there. in same time I wouldn't mind to have the data as long as it is small and compact.
So I've just had another search for websites that offer equinox times far into the future and except for one, they all differed from my results by far less than the aforementioned safety margin. Here are the websites: https://www.drikpanchang.com/seasons/season-vernal-equinox-timings.html http://www.newscotland1398.net/equinox/vern1788.html http://www.astropixels.com/ephemeris/soleq2001.html https://www.timeanddate.com/calendar/seasons.html?year=2100 Funnily enough, the one website that differs substantially is one by NASA https://data.giss.nasa.gov/ar5/srvernal.html But they make a lot of approximations and you can actually look at the code they used to produce it, which is quite simply way too short to be accurate :-)
@tarekgh If the data can be binary, I can get it down to just over 1kb including the lengths of Ayyám-i-Há, a little less excluding that. Edit: kb, not kB :-)
I wouldn't mind to have the data as long as it is small and compact.
I'd expect the amount of extra code to do the calculation would far exceed the extra 500 bits of data needed to embed the number of Ayyam-i-Ha days for 500 years. For each year, we'd need just 0 or 1 to indicate 4 or 5 days.
ok, thanks @janrg and @glittle
Per the discussion, I would say let's move forward with using @janrg data with suggested range. the data will include the Ayyam-i-Ha needed bits too. in the future, we can update the data as necessary. While this will be kind of breaking change, we can document that from now.
@glittle could you please update the proposal according to the discussions here?
Thanks. I should be able to update the proposal in the next two days.
The proposal is updated. Please let me know if I missed anything.
@glittle thanks for updating the proposal:
for
public override int GetLeapMonth(int year, int era) { -1 }
It should return 0 in case if we have leap year (i.e. Ayyam-i-Ha is 5 days)
other than that it looks good to me. Could you update the proposal one last time if you agree with my comment here?
Done. :)
I marked the issue as ready for design review. Let’s wait for that.
Thanks for the detailed proposal!
The cost for us to support a calendar can be high because we have to react if definitions or rules change. It seems neither Windows, nor macOS, nor ICU support this calendar natively.
Thankfully, the .NET globalization APIs are extensible so you'll be able to ship this calendar as a NuGet package. If it gets very popular, adding it to the platform seems reasonable. But considering that major vendors haven't added it, makes us believe it might not be popular enough to warrant us carrying the calendar -- and committing on keeping it up-to-date.
For now, I'll be closing this issue. Please feel free to reopen if you believe your package has become so popular that adding it the platform is sensible.
Hi @terrajobst.
As long as we implement just the core of the calendar, as proposed, there is little likelihood that the rules will change. The rules were "set in stone" in 2014 and can now be relied on. The only part that will need maintenance will be the small data table providing the timing of the vernal equinox each year. That is already defined for a few hundred years. The next refresh of that data table won't be needed for 50 - 100 years from now, which is likely beyond the lifespan of our current computer systems - I'm sure that a lot will change in that time!
It looks like this is a "chicken and egg" conundrum!
The Badíʿ calendar is relatively new and could only be easily implemented in computer code since 2014. As such, there is no way that older systems could have supported it. Its definition as a truly solar calendar tied directly to the equinox is unique and interest in using it is spreading. It is currently used mostly within a specific, global, religious community, but the calendar stands on its own, independent of that religion. Many people are seeking a meaningful trans-national calendar and this is a very good candidate!
To me, adding the calendar to the .NET Core is a good first step. The .NET Core is a dynamic system that is continuing to evolve quickly. Once that is in place, I was planning to propose the addition of the calendar to the ECMAScript standard. There are already a number of websites and apps that work with the Badíʿ calendar, and it would make that easier if JavaScript had built-in support for it. Beyond that, adding it to core OS systems would be considered.
I still hope that .NET Core could be the first of the "major" systems to include direct support for the Badíʿ calendar!
Hi @karelz. I see you changed the milestones, but this still seems to be closed. Can it be opened again?
Hi @glittle, will be better you start creating the NuGet package and have it ready anyway. The code will be ready if we decide to include this calendar in the core. We'll start recommending it to the users and monitor if it is getting more momentum and then will be easy to add it to the core. so, I am seeing getting the NuGet from now is good step either way.
I agree it makes a lot of sense to prepare a NuGet package and hold off on integrating it into core for now. While the calendar itself is unlikely to change, we could find that the API and surrounding design decisions need changes once we get more experience using this library in real software.
@karelz and @tarekgh... can you point me to some repositories that might serve as good examples of what you'd like to see? Ones that would be "close" to what could later be integrated into the core. That is, what sort of directory structure would be good, what naming conventions to use, etc.
The end result will likely be two packages... one with the core calendar and one that would provide extra services, as mentioned above.
@glittle you can create your own repo on github. you don't have to be restricted to any repo. Also, you can include everything in one package. that is easier for you and for the users too. In the future, if decided to port this calendar to the core, we can just pick the needed code manually and then ported to our core repos.
Thanks, everyone. I've started a project at https://github.com/glittle/Badi-Core. It may take a while before I'm able to do much work on it...
The Badíʿ calendar is a solar calendar where each year starts with the vernal equinox. It was developed and defined by the founders of the Bahá'í Faith in the mid to late 1800's A.D. The formal name, Badíʿ (بدیع), meaning something like wondrous, unique, marvelous, etc., includes an accented "i" and the Arabic ayin "ʿ". If these cannot be included in the code, simply using “Badi" without the accent and ayin is common. A reasonable pronunciation for a non-Arabic speaker is "ba dee".
The start of the first year of the Badíʿ calendar occurred in 1844 A.D. / 1260 A.H. / AM 5604. Years are labelled "B.E." for Bahá'í Era. The current year is 175 B.E. and it started at the vernal equinox that occurred in March 2018 A.D.
A year consists of 19 months, each with 19 days. Each day starts at local sunset. A group of 19 years is called a "Unity" (Váḥid) and a group of 19 Unities is called an "All Things" (Kull-i-Shay’).
A period of 4 or 5 days (called "Ayyám-i-Há" or "the days of Há") always occurs between the 18th and 19th months. The length of this period of intercalary days is solely determined by the number of days between the start (at the vernal equinox) of the current and following years. The vernal equinox is a momentary point in time, so the "date" of the equinox is determined by the date (beginning at sunset) in effect in Tehran, Iran at the moment of the equinox.
The calendar is described in more detail at https://wikipedia.org/wiki/Badi_calendar.
In .NET, the Badíʿ calendar will be implemented as a standalone calendar independent of any specific culture. While days technically start at local sunset, this implementation ignores that and only calculates the date of the main part of the day, from midnight to sunset.
Proposed API
Notes
Support package
Advanced formatting and information about special days would be provided by a NuGet package. This is outside the scope of this proposal but is mentioned here for completeness.
Formatting
One of the primary uses for the .NET Badíʿ calendar is likely to generate a text representation of the Badíʿ date. It is proposed to implement a “dual” language-specific formatting system using specialized tokens. Each day and month has a translated “meaning” and a transliterated Arabic name. For example, the 5th month, in English, is Light (Núr) while in Chinese it would be 光 (努尔) and in Russian Свет (Нӯр). In the proposed package, those would all be potential output from something like
badiDate.ToFormattedString("{month_meaning} ({month_arabic})")
. A sample set of possible tokens can be seen here.Religious use
The Badíʿ calendar has no intrinsic religious dependencies and can be used in any context.
However, just as the Gregorian calendar is used by the Christian religion to mark holy days such as Easter and Christmas, the Badíʿ calendar is used by the Bahá'í Faith to mark its holy days. For Christians, some of these days are fixed in the Gregorian calendar, like Christmas on December 25, and others float, like Easter on the 1st Sunday after the first full moon (sort of) after the vernal equinox. The Bahá'í Faith has 11 holy days, 9 of which are fixed in the Badíʿ calendar and 2 of which are floating. The floating days are the 2 days immediately following the 8th new moon after the vernal equinox. The dates of these floating days will come from a table of precalculated dates in the support package.
Tags @tarekgh @krwq