# ExCalendar

**URL:** <https://forum.elixirforum.com/t/excalendar/3239>\
**Category:** Announcing\
**Tags:** library, calendars\
**Created:** [January 11, 2017, 8:24pm UTC](https://forum.elixirforum.com/t/excalendar/3239 "2017-01-11T20:24:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [January 7, 2017, 8:08pm UTC](https://forum.elixirforum.com/t/excalendar/3239/1 "2017-01-07T20:08:09Z")

</div>

_Notice by @qqwy: This topic was split from the [Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/67) 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:

```elixir
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. ^.^

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [January 9, 2017, 2:53pm UTC](https://forum.elixirforum.com/t/excalendar/3239/2 "2017-01-09T14:53:48Z")

</div>

@OvermindDL1: I just pushed initial commit for project that visualize our idea: [ExCalendar](https://gitlab.com/ex-open-source/ex_calendar).  
I defined only two protocols and simple `ExCalendar.Calendar` module.  
Of course I’m not expert of English and calendars, so it’s not final version. For example in protocol methods declarations I used **Erlang** date/time `Tuple` as base format.  
What do you think about it?

---

<div class="post-metadata">

**Author:** ![OvermindDL1](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/32/2677_2.png) [@OvermindDL1](https://forum.elixirforum.com/u/OvermindDL1)\
**Post date:** [January 9, 2017, 4:40pm UTC](https://forum.elixirforum.com/t/excalendar/3239/3 "2017-01-09T16:40:19Z")

</div>

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/61):
>
> @OvermindDL1: I just pushed initial commit for project that visualize our idea: ExCalendar.  
> I defined only two protocols and simple ExCalendar.Calendar module.  
> Of course I’m not expert of English and calendars, so it’s not final version. For example in protocol methods declarations I used Erlang date/time Tuple as base format.  
> What do you think about it?

Hmm, not a bad start, but using the erlang date/time tuple still assumes things about a calendar that is _very_ likely not to exist in the future (we ‘are’ going to the moon and mars soon after all). This is why I still think that some amount of fixed time from a fixed point in spacetime is required as the base time unit (which for earth can just be seconds since the unix epoch, so unixtime, no leap second calculations or anything of the sort, just raw second or microseconds or attoseconds or whatever since the unix epoch). Calendar’s should be forced to convert to/from this relative spacetime value to their local representation (time is not a human construct, but dates are (based from a space and time)).

Or, could encode the location into the Calendar just by virtue of how it works, but again that means Date/DateTime/Time needs to be moved ‘into’ the calendar. ^.^

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [January 9, 2017, 8:40pm UTC](https://forum.elixirforum.com/t/excalendar/3239/4 "2017-01-09T20:40:40Z")

</div>

@OvermindDL1: yup, I know that **Erlang** date/time `Tuple`s are bad in our situation. As I already wrote it’s only a demo (initail release) - I used it, because temporary something should be there to let others know how it will be looks like in future (same as word **something** in one method). How about start date/event to compare time presentations? Is attosecond approved? If not I will wait for approved base time presentation for Elixir and update my work. Do you have any other tips? Am I missed an important method or something else?

---

<div class="post-metadata">

**Author:** ![Qqwy](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/qqwy/32/1349_2.png) [@Qqwy](https://forum.elixirforum.com/u/Qqwy)\
**Post date:** [January 10, 2017, 10:45am UTC](https://forum.elixirforum.com/t/excalendar/3239/5 "2017-01-10T10:45:03Z")

</div>

@OvermindDL1 I really like the idea of a fixed spacetime value of time. By chance, I happened to come across [Barycentric Dynamical Time (TBD)](https://en.wikipedia.org/wiki/Barycentric_Dynamical_Time) 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](https://en.wikipedia.org/wiki/Garbage_in,_garbage_out).

For most projects, a time representation like this is a very clear case of [YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it).

@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](https://en.wikipedia.org/wiki/Law_of_triviality) 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! 🙂  
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](https://en.wikipedia.org/wiki/Planck_time) is your best bet (also see [Orders of magnitude of time](https://en.wikipedia.org/wiki/Orders_of_magnitude_(time))).

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [January 10, 2017, 10:59am UTC](https://forum.elixirforum.com/t/excalendar/3239/6 "2017-01-10T10:59:42Z")

</div>

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/65):
>
> @OvermindDL1: yup, I know that Erlang date/time Tuples are bad in our situation. As I already wrote it’s only a demo (initail release) - I used it, because temporary something should be there to let others know how it will be looks like in future (same as word something in one method). How about start date/event to compare time presentations? Is attosecond approved? If not I will wait for approved base time presentation for Elixir and update my work. Do you have any other tips? Am I missed an important method or something else?

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](https://gitlab.com/ex-open-source/ex_calendar/blob/master/lib/ex_calendar/calendar/time_presentation_protocol.ex#L43)

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).

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [January 10, 2017, 4:49pm UTC](https://forum.elixirforum.com/t/excalendar/3239/7 "2017-01-10T16:49:29Z")

</div>

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/66):
>
> @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).

Right, it’s why pushed only **initial work** - for example without even simple “blank” implementation of calendar. It’s a skeleton that needs to be modified. We started from idea. Now lets make it usable!

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/66):
>
> 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.

agree

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/66):
>
> 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).

**Planck time** looks really good, but it’s ~5.39116(13)\*10^-44s, so we need to round it, right? Is it a good to use rounding on so small unit? How it could affect on much more higher like days, weeks, years?

> [@Calendars & Calendar Conversions](https://forum.elixirforum.com/t/calendars-calendar-conversions/3119/68):
>
> For example, such function makes no sense in a protocol: [Files · master · ex-open-source / ex\_calendar · GitLab](https://gitlab.com/ex-open-source/ex_calendar/blob/master/lib/ex_calendar/calendar/time_presentation_protocol.ex#L43)  
> 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.

True, it’s my bad.

I have an idea for new version. I will push it tomorrow. Thanks for your responses!

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [January 11, 2017, 8:24pm UTC](https://forum.elixirforum.com/t/excalendar/3239/8 "2017-01-11T20:24:03Z")

</div>

@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.  
😄
