October 12, 2010
Le 2010-10-12 ? 10:21, Andrei Alexandrescu a ?crit :

> On 10/12/2010 08:26 AM, Michel Fortin wrote:
>> A date can be expressed using different calendars, but can also be stored as an interval since a reference date (like the UNIX epoch). With your main storage format calendar-agnostic you can easily convert back and forth to different calendars-specific formats.
> 
> Interesting point. I wonder what Boost does.

Boost has posix_time::ptime which is basically a UNIX timestamp, then it has gregorian::date with fields year, month, and day. It's a little mixed-up, since posix_time depends on gregorian for some things, but beyond that if someone wanted to implement a different calendar, posix_time::ptime could easily serve as the common format between them.

Jonathan's datetime is pretty much a mirror of boost, with Date being the gregorian date, and SysTime being timestamp based, and they interact pretty much the same. Since you (Andrei) asked for Phobos datetime to be a port of boost::datetime, I'll have to say he has done a pretty good job at it. That said, I was never impressed much by boost::datetime for a couple of reasons (too many data types, coupling of calendar and time stuff), but doing things as I'd like them would probably be a major redesign and need more thinking; I don't want to force this on anyone.

For a date system that does support multiple calendars very well, take look at the Cocoa dates. Cocoa has NSDate which is basically a timestamp, NSDateComponents which contains a list of components for calendar dates and time of day, and the NSCalendar class that converts between the two.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



October 12, 2010
Le 2010-10-12 ? 14:08, Jonathan M Davis a ?crit :

> Except that most of the logic is going to be calendar-specific such that you really don't gain much by trying to separate out the calendar-specific logic. Date, DateTime, and SysTime all have a property to give you the Xth day since the beginning of the Proleptic Gregorian Calendar (dayOfGregorianCal IIRC), and SysTime has the stdTime property which gives you its internal representation of hecto-nanoseconds (100 ns) since midnight January 1st, 1 AD UTC, so all of the information necessary to convert to other calendar systems is there. But since most of the operations on Date, DateTime, and SysTime are specific to the Gregorian Calendar, I don't see much - if any - gain in trying to refactor out the non-calendar-specific stuff.

Don't misunderstand: I don't see much gain either.

The main gain (in my opinion) would be that it could make the API cleaner, but you have to weight it against the inconveniences: it would involve a major refactoring.

I don't think it's necessary, it's just something that itches me.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



October 12, 2010
On Tue, 12 Oct 2010 14:19:51 -0500, Michel Fortin <michel.fortin at michelf.com> wrote:

> For a date system that does support multiple calendars very well, take look at the Cocoa dates. Cocoa has NSDate which is basically a timestamp, NSDateComponents which contains a list of components for calendar dates and time of day, and the NSCalendar class that converts between the two.

Another good library that's calendar-agnostic is the Joda Time. It has several chronologies (calendars), like ISO8601, buddhist, coptic, ethiopic, gregorian, islamic, etc., that can be plugged dynamically. It's a very comprehensive library.

http://joda-time.sourceforge.net/

However. I don't think is that useful to have support for multiple calendars. I mean it's a cool thing to have, but honestly, how many programmers actually use Julian or Coptic calendars? It's a very niche usage of date and time programming constructs.

-- 
Yao G.
October 12, 2010
Le 2010-10-12 ? 15:37, Yao G. a ?crit :

> On Tue, 12 Oct 2010 14:19:51 -0500, Michel Fortin <michel.fortin at michelf.com> wrote:
> 
>> For a date system that does support multiple calendars very well, take look at the Cocoa dates. Cocoa has NSDate which is basically a timestamp, NSDateComponents which contains a list of components for calendar dates and time of day, and the NSCalendar class that converts between the two.
> 
> Another good library that's calendar-agnostic is the Joda Time. It has several chronologies (calendars), like ISO8601, buddhist, coptic, ethiopic, gregorian, islamic, etc., that can be plugged dynamically. It's a very comprehensive library.
> 
> http://joda-time.sourceforge.net/

Nice. I didn't know about this one.


> However. I don't think is that useful to have support for multiple calendars. I mean it's a cool thing to have, but honestly, how many programmers actually use Julian or Coptic calendars? It's a very niche usage of date and time programming constructs.

How niche it is, I wonder. If you're using dates from two centuries ago then you probably need support for Julian. Beyond that I don't really see a need. But I don't know either how much other calendars are still in use in other parts of the world... perhaps more than westerners are willing to admit.

An interesting observation is that Mac OS X gives me the choice of which calendar to use to display dates across the system. In the Language & Text system preference pane, I have the choice between Gregorian, Buddhist, Coptic, Ethiopic, Ethiopic (Amete Alem), Hebrew, Indian National, Islamic, Islamic (Civil), Japanese, Persian, and Republic of China. Perhaps they added this capability just to look cool, or perhaps it was to satisfy a demand from their customers. Again, I don't know the answer.

I know however that the niche feature of today can grow in the standard feature of tomorrow. Handling time zones was a niche feature once. Then every computer became interconnected and it became a must. Perhaps letting the user choose his calendar will become a standard part of software localization in a few years... it already is for Mac OS X.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



October 12, 2010
On Tuesday, October 12, 2010 13:31:02 Michel Fortin wrote:
> How niche it is, I wonder. If you're using dates from two centuries ago then you probably need support for Julian. Beyond that I don't really see a need. But I don't know either how much other calendars are still in use in other parts of the world... perhaps more than westerners are willing to admit.
> 
> An interesting observation is that Mac OS X gives me the choice of which calendar to use to display dates across the system. In the Language & Text system preference pane, I have the choice between Gregorian, Buddhist, Coptic, Ethiopic, Ethiopic (Amete Alem), Hebrew, Indian National, Islamic, Islamic (Civil), Japanese, Persian, and Republic of China. Perhaps they added this capability just to look cool, or perhaps it was to satisfy a demand from their customers. Again, I don't know the answer.
> 
> I know however that the niche feature of today can grow in the standard feature of tomorrow. Handling time zones was a niche feature once. Then every computer became interconnected and it became a must. Perhaps letting the user choose his calendar will become a standard part of software localization in a few years... it already is for Mac OS X.

The ISO standard is essentially the Proleptic Gregorian Calendar (proleptic in this case meaning that it uses the Gregorian Calendar calculations for all of time rather than just after the calendar was adopted). There are a few differences between the ISO standard and the traditional Proleptic Gregorian Calendar (like using year 0 for 1 B.C.), but it's essentially the same. Most of the world uses the Gregorian Calendar (including places like China, suprisingly enough). I don't know the exact list of countries where it's not used (it wouldn't surprise me if at least part of the Middle East didn't use the Gregorian Calendar for their normal time-keeping), but it's essentially the international standard.

And if you're worried about historical dates, that just plain gets messy. Different countries adopted the Gregorian Calendar at different times and in different ways (Sweden even did it in a manner which got them a February 30th: http://en.wikipedia.org/wiki/February_30th ). Historically, people didn't even necessarily start the year on January 1st, so exactly what date a historical date indicates can be a very tricky thing - far too much so for it to be particularly sane to try and have a date/time library handle it. Java's calendar library apparently uses the Gregorian Calendar for dates after its official adoption and the Julian for before, but that's got to be a bit messy and doesn't really solve the problem anyway.

I opted to keep it simple and implemented the Proleptic Gregorian Calendar (essentially following ISO 8601: http://en.wikipedia.org/wiki/ISO_8601 ). That's what Boost did as well, though for some reason, their stuff doesn't cover anything before the year 1400. My code covers B.C. as well as A.D.

I'm sure that there are applications which care about calendars other than the Gregorian Calendar, but I really do think that it's a niche need. As part of making the world interconnect better, a lot of this sort of thing is increasingly being standardized, so I would expect alternate calendars to actually be needed less rather than more.

- Jonathan M Davis
October 12, 2010
On 10/12/10 16:14 CDT, Jonathan M Davis wrote:
> I'm sure that there are applications which care about calendars other than the Gregorian Calendar, but I really do think that it's a niche need. As part of making the world interconnect better, a lot of this sort of thing is increasingly being standardized, so I would expect alternate calendars to actually be needed less rather than more.

Action item for me: I'll ask Jeff Garland about his experience with all that.

Andrei
October 12, 2010
Le 2010-10-12 ? 17:14, Jonathan M Davis a ?crit :

> I'm sure that there are applications which care about calendars other than the Gregorian Calendar, but I really do think that it's a niche need.

I agree to that it's niche, at least in the part of the world where I leave.


> As part of making the world interconnect better, a lot of this sort of thing is increasingly being standardized, so I would expect alternate calendars to actually be needed less rather than more.

That's a way to see things. But standardization doesn't always work, sometime because something is seen as a cultural icon, or it just takes much longer than you'd expect. How long did it take for everyone to abandon Julian and pass to Gregorian? Adoption: 1582 in Rome, 1752 for Britain, 1918 for Russia, 1924 for Greece. Total: 342 years; and all these countries were Christian.

Similarly to the Gregorian calendar being an ISO standard, you could say that English is becoming de facto the international language today. This hasn't reduced the need for localization in software, quite the contrary: as computers are used more and more everywhere, the need for localization increased as it reached less technically-minded persons.

And Wikipedia says that many calendars other than Gregorian are currently in wide use today:

"""
While the Gregorian calendar is widely used in Israel's business and day-to-day affairs, the Hebrew calendar, used by Jews worldwide for religious and cultural affairs, also influences civil matters in Israel (such as national holidays) and can be used there for business dealings (such as for the dating of checks).

The Iranian (Persian) calendar is used in Iran and Afghanistan. The Islamic calendar is used by most non-Iranian Muslims worldwide. The Chinese, Hebrew, Hindu, and Julian calendars are widely used for religious and/or social purposes. The Ethiopian calendar or Ethiopic calendar is the principal calendar used in Ethiopiaand Eritrea. In Thailand, where the Thai solar calendar is used, the months and days have adopted the western standard, although the years are still based on the traditional Buddhist calendar. Bah?'?s worldwide use the Bah?'? calendar.
"""
<http://en.wikipedia.org/wiki/Calendar#Currently_used_calendars>

Speaking of standardization: when is the US going to pass to the metric system? I don't really want an answer, but it shows that you shouldn't really count on standardization until has actually happened.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



October 12, 2010
On Tuesday, October 12, 2010 17:17:38 Michel Fortin wrote:
> Le 2010-10-12 ? 17:14, Jonathan M Davis a ?crit :
> > I'm sure that there are applications which care about calendars other than the Gregorian Calendar, but I really do think that it's a niche need.
> 
> I agree to that it's niche, at least in the part of the world where I leave.
> 
> > As part of making the world interconnect better, a lot of this sort of thing is increasingly being standardized, so I would expect alternate calendars to actually be needed less rather than more.
> 
> That's a way to see things. But standardization doesn't always work, sometime because something is seen as a cultural icon, or it just takes much longer than you'd expect. How long did it take for everyone to abandon Julian and pass to Gregorian? Adoption: 1582 in Rome, 1752 for Britain, 1918 for Russia, 1924 for Greece. Total: 342 years; and all these countries were Christian.
> 
> Similarly to the Gregorian calendar being an ISO standard, you could say that English is becoming de facto the international language today. This hasn't reduced the need for localization in software, quite the contrary: as computers are used more and more everywhere, the need for localization increased as it reached less technically-minded persons.
> 
> And Wikipedia says that many calendars other than Gregorian are currently in wide use today:
> 
> """
> While the Gregorian calendar is widely used in Israel's business and
> day-to-day affairs, the Hebrew calendar, used by Jews worldwide for
> religious and cultural affairs, also influences civil matters in Israel
> (such as national holidays) and can be used there for business dealings
> (such as for the dating of checks).
> 
> The Iranian (Persian) calendar is used in Iran and Afghanistan. The Islamic calendar is used by most non-Iranian Muslims worldwide. The Chinese, Hebrew, Hindu, and Julian calendars are widely used for religious and/or social purposes. The Ethiopian calendar or Ethiopic calendar is the principal calendar used in Ethiopiaand Eritrea. In Thailand, where the Thai solar calendar is used, the months and days have adopted the western standard, although the years are still based on the traditional Buddhist calendar. Bah?'?s worldwide use the Bah?'? calendar. """ <http://en.wikipedia.org/wiki/Calendar#Currently_used_calendars>
> 
> Speaking of standardization: when is the US going to pass to the metric system? I don't really want an answer, but it shows that you shouldn't really count on standardization until has actually happened.

All great points, though computers do tend to stick to standardization better than many other things (though all you to do is look at IE to know that that doesn't always happen either).

However, I still don't think that it makes much sense to worry about it for std.datetime, and I very much doubt that I would ever seriously consider writing a date/time library which really tried to worry about other calendars. If there are easy, non-intrusive ways to make it so that 3rd party libraries can use some of datetime to implement their own library code, that's fine, but I don't want to bend over backwards trying to get std.datetime to work with calendar functionality that doesn't and may never exist. So, stuff like durations, intervals, and ranges will likely be appropriately useable with other non- Gregorian date types, but I don't think that it's worth the extra cost to try and refactor out the portions of Date, DateTime, or SysTime which are calendar- agnostic - particularly when so little of it is likely to be calendar-agnostic.

I haven't look at the Cocoa API that you mentioned, and maybe they did a fantastic job of finding a way to do it, but from what I can see, the core stuff which would be calendar-agnostic is so small that there's really no value in trying to refactor it out. It would be so small that you might as well just reimplement it in non-Gregorian date types.

- Jonathan M Davis
October 14, 2010
OK, so I'll preface this by saying I've been out for the long weekend, then we had a family emergency, so I've been away from this mailing list since last Friday.  So I haven't had a chance to look at many of the discusions on this list about datetime (my unread messages on the Phobos list is 110 right now).

But as someone who's worked on datetime stuff in the past, I want to express my opinions of this.  I apologize if this version is completely out of date, or my points have already been brought up.

So here goes:

I have read some of the other posts about the module size, and here is my opinion: When you import a module, you don't care how many lines of code it is. All you care about is getting access to a feature of that module.  Often times, more is imported than is necessary, so I think from that perspective, it doesn't matter how big the module is.  40,000 LOC seems like a lot, but much of this is very rote very boilerplate code, so I think the generated result is not going to reflect that as much.  When you go two levels deep, also remember that this bloats the executable because the full module name is used to mangle all symbols.  Regarding docs, the doc generation is not a problem of having too large modules, it's more of a problem of the doc generator not organizing the output very well.  Finally, in my experience, very few import the specific modules they want, they just import everything.  Most java programs don't import java.io.xyz, they import java.io.*.  What you are doing by splitting the code into submodules is making it awkward to do this at best.  I never really liked the 'all' solution.  My opinion is that you just have all the code in one module, and not worry about the size.

----

I read the blurb from your original email about how everything is laid out. Without looking at the code yet, I think all the limits and decisions seem OK. A couple things that came up with my implementation of datetime on Tango:

1. Are you going to use an extended Gregorian calendar, or use a Julian calendar for the appropriate dates?  I recommend using extended Gregorian, because it's much easier to deal with, and anyone who wants to deal with such historic accuracy should be using a much more complete library.  In any case, it should be noted what you are using.

2. I highly recommend ignoring the concept of leap-seconds, as it just adds constant maintenance (since leap seconds cannot be predicted) and doesn't add much to the library.  However, it should be noted whether you support them.

----

I don't like all the aliases for Year, etc.  This accomplishes almost nothing except documentation.  And even that doesn't add much.  I don't see the point of doing:

int foo(Year years)

vs.

int foo(short years)

Both seem equally documented to me.

----

I like the to!(TUnit, TUnit) conversion function, but I think it is redundant to also have daysTohnsecs (btw, this isn't properly cased, I think it should have been daysToHnsecs).  I see the first uses the other, but a better implementation is possible without requiring all the others.  Also, you risk unnecessary truncation in your calculations.

I'd say get rid of all the extra functions.  I would also renumber the enum for TUnit to go from smallest to largest, and I would rewrite the to conversions as:

template hnsecPer!(TUnit un) if(TUnit >= TUnit.week) // note reverse this if you
reorder enum
{
    static if(un == TUnit.hnsec)
        enum hnsecPer = 1L;
    else static if(un == TUnit.usec)
        enum hnsecPer = 10L;
    else static if(un == TUnit.msec)
        enum hnsecPer = 1000 * hnsecPer!TUnit.usec;
    else static if(un == TUnit.second)
        enum hnsecPer = 1000 * hnsecPer!TUnit.msec;
    else static if(un == TUnit.minute)
        enum hnsecPer = 60 * hnsecPer!TUnit.second;
    else static if(un == TUnit.hour)
        enum hnsecPer = 60 * hnsecPer!TUnit.minute;
    else static if(un == TUnit.day)
        enum hnsecPer = 24 * hnsecPer!TUnit.hour;
    else static if(un == TUnit.week)
        enum hnsecPer = 7 * hnsecPer!TUnit.day;
    else static assert(0);
}

...

    static long to(TUnit tuFrom, TUnit tuTo)(long value) pure nothrow
        if(tuFrom >= TUnit.week && tuFrom <= TUnit.hnsec &&
           tuTo >= TUnit.week && tuTo <= TUnit.hnsec)
    {
        static if(tuFrom > tuTo)
            return value * (hnsecPer!tuTo / hnsecPer!tuFrom);
        else
            return value / (hnsecPer!tuFrom / hnsecPer!tuTo);
    }

(Note -- untested)

----

toString!(TUnit) -- this seems like an extremely fringe need.  Not often do I care about printing a value representing seconds.  More often I care about printing a duration, time of day, or a date.  Can we drop this and functions that depend on it?

Also note that string representation of date/time is one of those things that is highly sensitive to locale.  Tango has a ginormous library dedicated to printing locale-dependent stuff including date/time.

I agree that having a default print for date/time is fine, esp. for debugging, but let's not try to reinvent formatted printing in the date time module.

----

timeT2StdTime and stdTime2TimeT -- I really don't like the names here.  Can we
call it C Time?  T has such a known usage as representing a generic type, this
was my immediate thought of what it does.  In Tango, we called it toUnixTime and
fromUnixTime.  Also, don't abbreviate to as 2.  I hate that :)

Also, I don't think we need another version of this
(fromTimeTEpoch2StdTimeEpoch), if you have the wrong unit, just use the to!
functions defined above.

----

I'll echo what I've read from Andrei -- I don't like using classes as namespaces.  Find another way.

----

Encountered more string processing functions in core.d.  Can we agree to print a date/time out like this:

[mm/dd/yyyy] [hh:mm:ss.ffffffff]

Where mm is month, dd is day, yyyy is 4-digit year, hh is 24-hour hour, mm is minute, ss is second, and ffffff is fractional seconds.

And for durations, we should come up with a similar format.  C# I think uses ddd.hh:mm:ss.ffffff where ddd is the total number of days.

If we can do this, then I think we can leave the pretty-printing of anything else to a locale-based formatting library.  People are going to want to use their own locale anyways.

----

General nitpick comment, your ddoc is over 80 chars wide (over 100 in some spots), can you fix this?  I don't mind code being wider than necessary, but comments should fit within an 80xN terminal.

----

In e.g. HNSecDuration.msecs, you are using a very convoluted way to get the number of milliseconds :)  Use mod instead.

And in general, can we just use a template?  If we continuously parameterize everything based on the unit type, generic programming is going to be much easier.

i.e.

@property long get(TUnit unit type)() {...}

alias get!(TUnit.msec) msecs;
...

----

I think we also need totalX where X is Msecs, Secs, etc.  For instance, you may only care about how many days you have, and not how many weeks.  So to get the total number of days, you would currently have to do x.weeks * 7 + x.days.  If you wanted the total milliseconds, it would be worse.

This can also be a generic template with aliases.

----

JointDuration -- aside from operators, do we need to wrap the other methods of HNSecDuration and MonthDuration?  Can we just provide accessors for the MonthDuration and HNSecDuration (in fact, you may want this).

----

TimeOfDay: Can we use HNSecDuration with an invariant that it's < 24 hours?  I can't see why you'd want to reimplement all this.  FWIW, Tango uses Span (the duration type) as it's timeofday component.

Date is one thing -- the durations are based on a point in time.  But time of day is always the same no matter the day.

I'd expect the following structs in timepoint.d:

Date -- a date with the fields year month day
Time -- A HNSecDuration with the limitation that it must be less than  24 hours
DateTime -- a combination of both Date and Time

As far as time zone, I've not yet dealt with it.  It was on my plate to add time zones to Tango, but I never got around to it.  I think a type that combines a point in time with a time zone might be the best solution, similar to how an interval combines a point in time with a duration.

You have other time types in timepoint which I think are not necessary.  Like FracSec.

---

OK, so that's what I have.  I think it's a very well thought out lib, it just needs to be trimmed down.

One final thought -- after reading through all the stuff, unit tests take up the vast bulk of the lines of code.  I think it's safe to say the .di file would be like 5000 LOC.  I think it definitely should be one file.

-Steve


----- Original Message ----
> From: Jonathan M Davis <jmdavisProg at gmx.com>
> To: phobos at puremagic.com
> Sent: Fri, October 8, 2010 5:59:17 PM
> Subject: Re: [phobos] datetime review (new attempt at URL)
> 
> Okay. Hopefully this URL  works:
> 
> http://is.gd/fS35q
> _______________________________________________
> phobos  mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
> 



October 14, 2010
On Thu, Oct 14, 2010 at 11:38 PM, Steve Schveighoffer <schveiguy at yahoo.com> wrote:
> Can we agree to print a
> date/time out like this:
>
> [mm/dd/yyyy] [hh:mm:ss.ffffffff]
>
> Where mm is month, dd is day, yyyy is 4-digit year, hh is 24-hour hour, mm is minute, ss is second, and ffffff is fractional seconds.
>

This is actually very locale-specific. E.g. here in Russia we use dd/mm/yyyy (I'm used to it and it seems pretty logic - the order is ascending), and thus when I see 5/6/2010 I always confuse if it's May, 6 or June, 5.