Jalaali (Shamsi) calendar for elixir (Persian calendar)

I don’t think so. The plan is to have functions that accept calendars as arguments as well as conversion functions to a fixed timestamp, although I am not sure if that timestamp will be the unix epoch.

2 Likes

@josevalim yes since we are dealing with only Dates and many of them may be behind 1970 unix epoch is overkill, i can suggest using Julian Day Calendar (JDN) as that fix timestamp. it simply represents number of days passed After Christ (AC or Positive integer) or Before Christ (BC or Negative integer)

In Jalaali i’m using JDN. whenever trying to convert from/to gregorian/jalaali im converting input date in Julian days and from Julian days i calculate specified date time.

1 Like

@josevalim Now that i think, i highly recommend using unix epoch as timestamp.

  • We already have Calendar.ISO.from_unix
  • Since in Date.utc_today and DateTime.utc_now, Elixir is using erlangs :os.system_time

I think if we use unix epoch we will have no overhead in this.

Am i wrong?

At the moment I don’t have enough background on supoorting multiple calendars to say if this should be our choice or not. For example, UNIX does not have leap seconds. So I don’t know if this is an issue or not.

1 Like

@josevalim sure it should be researched! but since leap seconds are added to each calendar differently, i don’t think UNIX will create a problem with that.

I don’t have enough background on that too, but because is my country more than several different calendars are being used, i have worked with many calendars programmatically. i can research on them and help in finding the best solution.

Anyways, is it possible for me to start working on this issue? I would be really happy :slight_smile:

2 Likes

Yes, please! Implementation is likely the easy part, researching and figuring out how other implementations work is the one that takes more time, so help is definitely appreciated.

3 Likes

You may want to consider looking at the Joda-Time Java library for inspiration. It supports several calendar systems. Although it doesn’t support Jalaali, there’s a fork that does.

I’m afraid I don’t have a lot of experience with conversions between calendar systems across time and space, but I know Joda is fairly respected.

2 Likes

@josevalim i will do my best on this. Thank you. :wink:

@jmitchell thank you very much for the hint! :slight_smile:

Let me clarify that I’m not at all an expert at time systems, but having a love of clocks, astronomy and weird human constructs here are my two cents:

  • To make precise timestamp conversions between two different calendars, it is useful to find a simple and unambigous (i.e. no discontinuities like leap days, daylight savings time, leap seconds etc.) ‘standard’ intermediate representation.
  • I might be wrong, but the TAI (International Atomic Time) seems to fit this description. This is the standard that is used in, amongst other places, space travel. It does not use leap days or leap seconds. It simply counts time (in SI-seconds) since the defined starting point. The timescale used by the GPS might be even easier to use (it it always exactly 19 seconds behind TAI, but otherwise is the same) as its starting point is equal to 1958-01-01 0:00 UTC.

Joda time indeed is a great reference; I really like their approach to Periods (a set of amounts, i.e. some days, some hours, some minutes, some seconds that are added in turn and thus keep in mind discontinuities like daylight savings time.) vs Durations (an exact amount of milliseconds.)

4 Likes

So far, Joda-Time is using epoch to achieve calendar (Chronology as they call it) conversion. Source

Probably this type of conversion does not support leap seconds. actually since leap seconds that adde to UTC do not have an algorithm, it may be impossible to support them in conversion.

Another issue that i have seen here is in DateTime.utc_now, Elixir uses erlang’s :os.system_time which does not count leap seconds either.

I personally don’t recognize this as issue because there is no documentation on how to decide whether or not this year contains a leap seconds. According to Wikipedia Insertion of each UTC leap second is usually decided about six months in advance by the International Earth Rotation and Reference Systems Service (IERS). (Source)
Even in Java, C# and other common langs, Leap seconds are not taken into account for their standard DateTimes Implementations.

I think (i need to research more about this) the advance of leap seconds is handled in OS by resync with an NTP. it should not be considered in Elixir’s standard Calendars or DateTimes.

If anyone has any ideas or believes i’m wrong about this, please tell me!

Researching continues…

2 Likes

Hey everyone

First of all i wanted to thank @Qqwy and @jmitchell for their useful posts.

Okay,

Here is what i finally found analyzing DateTime implementations of Java (Joda-Time), C#, Python:

  • Joda time is using UNIX timestamp to convert different Calendars (They call it chronologies) to each other (Link)
  • C# native DateTime only supports Gregorian calendar. convertors in its Globalization (Like PersianCalendar class) do not return a DateTime on convert. they only can return year, month, day of a given date to another calendar such as Jalaali, BUT it uses Gregorian day number as a timestamp
  • In python, there is nothing native for this problem, you should implement your new DateTime for it

NOTE: None of the implementations i see or read about has handled leap second problem, since leap seconds cannot be predicted because IERS will decide whether or not to add it (Link)

So it leads to these two decisions:

  1. Using UNIX as timestamp
  2. Using JDN (Julian day number) or GDN (Gregorian day number)

I vote for UNIX. because in Elixir, DateTime.utc_now or Date.today we are currently using :os.system_time so using UNIX wont add any overhead to code. but if we use JDN or GDN or anything else, we should afford a Date convert from UNIX to that timestamp.

So, What do you guys think?

(PS: @josevalim should i create an issue on github for this?)

1 Like

Have you had a chance to look at International Atomic Time (TAI) as suggested by @Qqwy? It seems preferable as a base measure of time because unlike other systems, it increases monotonically. As I understand it, TAI makes it possible to accurately describe “real” elapsed time, even when it differs from the time elapsed according to our clocks.

I see a couple potential downsides to TAI:

  1. as leap seconds are scheduled, we’d have to patch the conversion functions between it and UTC/UNIX time.
  2. generally other programming languages aren’t using it by default, and developers may expect elapsed times based on human clocks rather than “real” elapsed time.

Don’t hesitate to point out other concerns. I’m an amateur when it comes to timekeeping.

Should TAI be a first-class language feature or relegated to a library? UNIX time seems like the next best option if we don’t go with TAI.

I’ve posted a PR for discussion that uses the strategy used by Dershowitz and Rheingold in Calendrical,Calculations. This code only focuses on dates - not times - and uses the same convertable epoch approach. The PR is at https://github.com/elixir-lang/elixir/pull/5603. Comments and suggestions welcome.

The main advantage of this approach is that all of the calendar types in Calendrical Calculations that confirm to a {year, month, day} shape can be implemented using the Calendar behaviour. I added to the behaviour functions to convert to/from an integer date.

Also added a Date.diff/2 and protocol support to enumeration for a date range.

It would be pretty trivial to change from an integral number of days to a TAI or other time stamp. In fact that would help with some calendars that are based on start-of-day being noon rather than midnight and for calendars (like the Persian) that calculate leaps years based upon solar observation.

@jmitchell i have a question about TAI. presume you want to get current time from system. you don’t have a TAI clock there, only UNIX. UNIX does not count leap seconds. so i think if you want to do that, you should know when there are leap seconds? right?

Maybe i did not understand it good!?

@kip Thank you for implementing this. it is a good implementation but i think it is a little too complex for anyone who is going to implement their new Calendar to understand integer_date and change their basis for conversion on that!

What do you think?

I have implemented UNIX method in a bit lighter way. it is on pull #5609

Please do review it and if you think it is ok, lets check it for bugs.

I think calendars are complicated :slight_smile:

Even for your own calendar the official determinations require astronomical calculation of whether the vernal equinox before true noon. That’s way more complex.

In order to convert between calendars there needs to be some common representation, ihink that’s agreed. If it’s to be the Gregorian calendar (which he unix timestamp ultimately is) then that’s fine. However I don’t think the burden of calculator is any greater than the one I’ve described.

The reason I suggested the basis I did is that the means to calculate he integer date (called fixed date by Dershowitz and Rheingold) is that hey have already defined the conversations for 23 different calendars including arithmetic and astronomical calendars.

Therefore I would argue that the calculation comolexity is actually reduced because D&R have already done the hard work.

Last point, but I think it’s relevant - using a unix timestamp means you’re now taking responsibility for time as well as date. Dates are complex enough, time is really hard, The recent challenges of the the leap second illustrate that.

2 Likes

I agree, calendars are complicated!

First of all, Unix timestamp is NOT Gregorian calendar. UNIX counts milliseconds from 1970,1,1 right?
Now suppose Jalaali calendar. Can we say UNIX is number of milliseconds from 1348,10,11? Answer is YES. so UNIX is not a Gregorian calendar

In case of leap seconds, think you are going to get current system time and you are not connected to internet. So you don’t know if 2016 had a leap second. same problem happens with Integer day number here.

Another thing is, if we use Day number. we are adding complexity for developers who want to implement Calendars for elixir. I did’t find any platform that currently uses Day number for conversion. if you had, please share it.

Cheers! :slight_smile:

Hmm…, the UNIX (Or, to be precise, POSIX) time counts seconds (but subdividing these in milliseconds or smaller is allowed.) from 1970-01-01T00:00:00.00, but defines a ‘day’ to contain exactly 86400 seconds. This means that when an UTC day (either december 31st or june 30th) contains a leap second, the POSIX time needs to be adjusted. This is done differently by different organizations/implementations.

  • One possibility is to ‘jump back’ after the leap second was done. (This is what systems following the POSIX standard strictly are supposed to do, I believe, but for many computer systems this is unacceptable as incoming events are no longer ordered.)
  • Another possibility is to not update the POSIX timestamp at all during the leap second.
  • Another possibility is to ‘slow down’ time slightly during the time around the leap second: This is the so-called ‘leap smear’ that e.g. Google uses.

This means that POSIX time follows UTC except during leap seconds. Oddly enough, that in turn means that if we want to find out the TAI from a given POSIX timestamp, we actually need to know the amount of leap seconds that has passed (because these are implicitly part of the POSIX timestamp!). Still, because TAI does increase monotonically during leap seconds, it is a better standard for timestamp conversion. After all, it is only UTC -> TAI and TAI -> UTC that needs to handle the leap second problem.

In the case a computer is fully disconnected from the internet, its clock will start to diverge (regardless of what representation we use). The OS-clock will not count leap seconds in that case either way, because it has no way of knowing about them (when connected, the Network Time Protocol (NTP) is often used to regulate leap seconds). Also, a computer clock simply is not as precise as an atomic clock.

Yes, I think that would be the proper way to go. :slight_smile:

@Qqwy I don’t understand! :sweat:

Can you explain this issue to me:

Think you want to convert 2054,1,7 to another calendar. how can this method handle leap seconds?