Eiji

Eiji

ExCalendar

Notice by @qqwy: This topic was split from the Calendars & Calendar Conversions topic, which is about how calendars should be implemented inside Elixir Core. The idea of a separate ex_calendar library started with this post by @OvermindDL1:


Just a brain dump here since I am sick. ^.^

Not all Calendars use a year/month/day/hour/minute/second/etc… construct, so putting that as a base-most Date/DateTime structs was a very very bad move. Each Calendar should have its own Date/DateTime structs, which also allows easy matching on:

def do_blah(%Calendar.Gregorian{year: year, month: month, day: day}), do: gregorianStuff(year, month, day)

def do_blah(%Calendar.Bloop{egrek: egrek, vreenoop: vreenoop}), do: bloopStuff(egrek, vreenoop)

# Using expede's type_class (finally hit 1.0.0 whoo!) style here to force a set of generic conversions for calendar types
def do_blah(someOtherCalendar), do: Calendar.convertToCalendar(Calendar.Gregorian) |> do_blah

The above last line should use a direct conversion if one exists from calendar type to the given calendar type, else it should fall back to a mandatory conversion to some universal time storage type that could be something like: %UniversalTime{attosecondsSinceBaseTimeInObject:int, baseObject:atom|binary} where attosecondsSinceBaseTimeInObject would be the number of attoseconds since some arbitrary base period for the given baseObject, which could be its existence setup or something, and baseObject is the relative object that the relative time is for, which would default to :earth or so. Converting a UniversalTime for an object like :mars to some calendar like Calendar.Gregorian makes no sense and should exception or something, instead you’d need to calculate the relative earth time from mars first, also handled by the type_class/protocol by getting the relative calculations from the objects based on velocity and such, but for something like :earth/:mars you could pretend that is just 0 probably, this is all internal stuff that an external user would not use directly in most cases of course, though if you are making a relativistic simulation it could be quite useful externally, but mostly it is just for calendar conversions.

TL;DR: Date/DateTime should not be a global structure, every calendar could potentially represent Date/DateTime differently and they should be calendar specific. You can use protocols or type_class’s or so to get generic information out of ‘any’ calendar of course.

I’m going to lay back down for a bit. ^.^

Most Liked

josevalim

josevalim

Creator of Elixir

I think your library should not be concerned about creating data structures. The question you should answer is: assuming that many calendar structures exists, how can I work with them without caring about their representation? That’s when a protocol comes in.

For example, such function makes no sense in a protocol: Files · master · ex-open-source / ex_calendar · GitLab

Remember that the first argument of a protocol function is what we use for dispatching. In this function, the first argument will always be tuples, which means we will always dispatch to the tuple implementation and therefore you will never be able to create different data types.

I believe instead you should focus on the functions required for calendar interoperability. For example, imagine you want to calculate the difference between two dates in different calendars, how would you do that? You could for example add diff to the protocol… but wouldn’t it be more productive to simply have a common format both dates would be converted to and then you operate on that format?

Similarly, how do you add days to a given date in any calendar? Again, you could define an add function. But, if possible, wouldn’t be better to once again convert to a common format then perform the operation?

A good protocols finds the smallest API surface require to provide its functionality (which is one of the main reason protocols do not allow default implementations).

Qqwy

Qqwy

TypeCheck Core Team

@OvermindDL1 I really like the idea of a fixed spacetime value of time. By chance, I happened to come across Barycentric Dynamical Time (TBD) on Wikipedia a few times ago, which is exactly that.
However, I do want to note that when you’re working with a representation like this, then what you’re doing is rocket science: Calculating to- and with this format is going to involve very difficult (relativistic) calculations.

Also, for most computers that do not directly keep time with an atomic clock, the input timestamp will be too unprecise to calculate results that would actually be useful for rocket science; Garbage In, Garbage Out.

For most projects, a time representation like this is a very clear case of YAGNI.

@Eiji Writing some code so you have something to talk about is good. However, keep in mind that it is very easy to let a discussion move towards bikeshedding when you start filling in details too quickly, before the problem in general is fully described/known. Furthermore, it is easy as a human to pick ‘a solution algorithm’ right away, before thinking about all subproblems of the main problem. This results in code that does not solve the main problem fully, which means that it will need to be rewritten later (and this might be a lot of work if you find out about this).
That being said: I love your enthusiasm! :slight_smile:
To address the questions you have about your current code:

  • Instead of using a date/time Tuple, I would suggest using a custom struct that is defined as part of ExCalendar. Any other modules that want to alter something of this struct should do so by calling methods on the Struct’s module (so not by changing the fields of the struct directly). This keeps you free to completely overhaul the internal representation of the struct later.
  • As for what kind of base time representation unit you’d want to use: @OvermindDL1 probably also has an opinion about this (and I believe he knows more about Physics than I do), but I think Planck time is your best bet (also see Orders of magnitude of time).
Eiji

Eiji

@josevalim @Qqwy @OvermindDL1: just pushed new version of ex_calendar.
I added unit behavior, so any developer may easy work only on units. I changed definition of time presentation from protocol to behavior, because I think it will work better here. Calendar is still protocol, so we can list all it’s implementations. Calendar (as in previous version) have method to list supported time presentations and finally time representation have callback to list all supported units. Both time presentation and unit have callbacks to convert from and to universal unit. I added also some method ended with ! character, so we can check or just raise if passed unit name (like :hour) is supported or not. I also updated description and added one more diff method that returns value in universal unit. At end I added translate_units method, so developers do not need to care if they should add 0.5 minute or 30 seconds (I mean: what to use? Float or Integer or any of them? - no matter just translate them).
I hope that I don’t forgot about anything. Maybe some names are still bad (sorry for my English), but I believe that new version of skeleton is now much more better and closer to resolve main problem.
:smile:

Last Post!

Qqwy

Qqwy

TypeCheck Core Team

2 posts were merged into an existing topic: Calendars & Calendar Conversions

Where Next?

Popular in Announcing Top

Qqwy
Hello everyone, I wrote a small library today called MapDiff. It returns a map listing the (smallest amount of) changes to get from map...
New
alisinabh
Hey everyone i’ve developed a library for Jalaali calendar for elixir which supports converting Gregorian dates to Jalaali and vice vers...
New
OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
danschultzer
In short Plug n’ play OAuth 2.0 provider library. Just set up a resource owner schema with Ecto (your user schema), install the dependen...
New
trisolaran
Hi! :waving_hand: I would like to present LiveSelect, a little library that I wrote to easily add a dynamic selection input to your LV f...
198 11220 107
New
zachdaniel
Ash Framework What is Ash? Ash Framework is a declarative, resource-oriented application development framework for Elixir. A resource can...
New
Flo0807
Hello everyone! I am excited to share our heart project Backpex with you. After building several Phoenix applications, we realized that...
New

Other popular topics Top

KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36654 110
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement