Getting an era's beginning date

  • What's the best way of getting the start date for a given era in an
    NSCalendar?

    For days, weeks, etc. this is trivial, since they have a universal
    start time. But an era can begin and end at any point in time. These
    points in time are trivial to figure out on the Gregorian calendar
    (the AD era began on January 1, 1), but the Japanese calendar is a
    totally different story (the Heisei era began on January 7, 1989 for
    example).

    I've tried to solve this by polling NSCalendar for era changes, by
    getting the date for the first day in the era (which may not actually
    be in the era) and stepping through days until the era of the day
    matches the desired era, but this takes way too long to calculate for
    all eras on the Japanese calendar, so I'm hoping there's a better way.

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • Hi, Nick

    On 2008/01/29, at 8:49, Nick Zitzmann wrote:
    > For days, weeks, etc. this is trivial, since they have a universal
    > start time. But an era can begin and end at any point in time.
    > These points in time are trivial to figure out on the Gregorian
    > calendar (the AD era began on January 1, 1), but the Japanese
    > calendar is a totally different story (the Heisei era began on
    > January 7, 1989 for example).

    I am a Japanese.

      "January 7, 1989" is the date that our current emperor was
    enthroned. Each emperor had his own eras. Some emperors changed their
    eras when a disaster or evil thing had happened.
    As our imperial family has continued for more than 2000 years, there
    are hundreds of eras in Japanese calendar.

    I don't think it is realistic for NSCalendar to have Japanese era
    database.
    As our emperor's birthday is a national holiday, I know the date.
    But I don't remember the date when Heisei era began. :-)

    I am rather interested in Maya calendar that defines the date of the
    end of the world. :-)

    Satoshi
    -----------------------------------------------------
    Satoshi Matsumoto <satoshi...>
    816-5 Odake, Odawara, Kanagawa, Japan 256-0802
  • On Jan 28, 2008 4:39 PM, æ…§ æ?¾æœ¬ <satoshi...> wrote:
    > Hi, Nick
    >
    > On 2008/01/29, at 8:49, Nick Zitzmann wrote:
    >> For days, weeks, etc. this is trivial, since they have a universal
    >> start time. But an era can begin and end at any point in time.
    >> These points in time are trivial to figure out on the Gregorian
    >> calendar (the AD era began on January 1, 1), but the Japanese
    >> calendar is a totally different story (the Heisei era began on
    >> January 7, 1989 for example).
    >
    > I am a Japanese.
    >
    > "January 7, 1989" is the date that our current emperor was
    > enthroned. Each emperor had his own eras. Some emperors changed their
    > eras when a disaster or evil thing had happened.
    > As our imperial family has continued for more than 2000 years, there
    > are hundreds of eras in Japanese calendar.
    >
    > I don't think it is realistic for NSCalendar to have Japanese era
    > database.

    But it obviously *has* such a database. How else would it know which
    era to display when presenting dates to the user?

    If I set the system clock to 1989.01.07, it knows that that was in the
    Showa era, while if I reset it to the present, it knows that it is in
    the Heisei era; so the information is *somewhere*.

    > As our emperor's birthday is a national holiday, I know the date.
    > But I don't remember the date when Heisei era began. :-)
    >
    > I am rather interested in Maya calendar that defines the date of the
    > end of the world. :-)

    --
    Clark S. Cox III
    <clarkcox3...>
  • On Jan 28, 2008 AD, at 5:39 PM, æ…§ æ?¾æœ¬ wrote:

    > I don't think it is realistic for NSCalendar to have Japanese era
    > database.

    I'm pretty sure it does, since the names of the eras come from
    somewhere. If, for example, you set your system clock to some time in
    1870 and turn on the Japanese calendar in the International preference
    pane, then the year & era will be "3 Meiji" instead of 1870. I was
    trying to figure out where these eras started so I didn't have to poll
    the system for the data.

    But it doesn't matter too much, since I was able to work around the
    problem by using -[NSDateFormatter eraSymbols], where the symbol
    indexes are a perfect match for the era numbers on the Japanese
    calendar. I was hoping it would be possible to not make this
    assumption, but at least it solves the problem for now...

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On å¹³æˆ? 20/01/28, at 16:39, æ…§ æ?¾æœ¬ wrote:

    > On 2008/01/29, at 8:49, Nick Zitzmann wrote:
    >
    >> For days, weeks, etc. this is trivial, since they have a universal
    >> start time. But an era can begin and end at any point in time.
    >> These points in time are trivial to figure out on the Gregorian
    >> calendar (the AD era began on January 1, 1), but the Japanese
    >> calendar is a totally different story (the Heisei era began on
    >> January 7, 1989 for example).
    >
    > I am a Japanese.
    >
    > "January 7, 1989" is the date that our current emperor was
    > enthroned. Each emperor had his own eras. Some emperors changed
    > their eras when a disaster or evil thing had happened.
    > As our imperial family has continued for more than 2000 years, there
    > are hundreds of eras in Japanese calendar.
    >
    > I don't think it is realistic for NSCalendar to have Japanese era
    > database.

    Realistic or not, they did it. =)  I think the Japanese calendar
    support was added in Tiger; the era names go back to Taika in 645 AD.
    I found that I can get at least the year by using something like this:

    jp = [[NSCalendar alloc] initWithCalendarIdentifier:@"japanese"];
    components = [NSDateComponents alloc] init];
    [components setEra:235]; // Heisei; Taika is 0.
    date = [jp dateFromComponents: components]; // date is 1989-01-01
    00:00:00 -0800

    Notice, however, that the day is wrong.  I don't know if that's a
    deficiency in my code or in the era data itself.

    --Chris Nebel
  • On Jan 28, 2008, at 9:11 PM, Christopher Nebel wrote:

    > Realistic or not, they did it. =)  I think the Japanese calendar
    > support was added in Tiger; the era names go back to Taika in 645
    > AD.  I found that I can get at least the year by using something
    > like this:
    >
    > jp = [[NSCalendar alloc] initWithCalendarIdentifier:@"japanese"];
    > components = [NSDateComponents alloc] init];
    > [components setEra:235]; // Heisei; Taika is 0.
    > date = [jp dateFromComponents: components]; // date is 1989-01-01
    > 00:00:00 -0800
    >
    > Notice, however, that the day is wrong.  I don't know if that's a
    > deficiency in my code or in the era data itself.

    The date is actually correct. This is why I wanted to know the method
    of getting an era's beginning date, because eras, unlike years,
    months, and days, can begin and end at any time on a calendar.

    In the case of the Japanese calendar, the 235th era is indeed the
    Heisei era, but since you didn't specify year & date components,
    NSCalendar assumes you meant the first year/month/day in that time
    frame. The first year of the Heisei era is 1989, but January 1, 1989
    is actually in the Showa (234th) era.

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On 2008/01/29, at 13:11, Christopher Nebel wrote:
    > Realistic or not, they did it. =)  I think the Japanese calendar
    > support was added in Tiger; the era names go back to Taika in 645 AD.

    Great!!  I thought it was hard coded.

    You can see the Japanese eras (Gengou) and their start dates as bellow.
    http://homepage1.nifty.com/gyouseinet/history/gengouichiran.htm

    Satoshi
    -----------------------------------------------------
    Satoshi Matsumoto <satoshi...>
    816-5 Odake, Odawara, Kanagawa, Japan 256-0802
  • On Jan 28, 2008, at 8:31 PM, Nick Zitzmann wrote:

    > On Jan 28, 2008, at 9:11 PM, Christopher Nebel wrote:
    >
    >> Realistic or not, they did it. =)  I think the Japanese calendar
    >> support was added in Tiger; the era names go back to Taika in 645
    >> AD.  I found that I can get at least the year by using something
    >> like this:
    >>
    >> jp = [[NSCalendar alloc] initWithCalendarIdentifier:@"japanese"];
    >> components = [NSDateComponents alloc] init];
    >> [components setEra:235]; // Heisei; Taika is 0.
    >> date = [jp dateFromComponents: components]; // date is 1989-01-01
    >> 00:00:00 -0800
    >>
    >> Notice, however, that the day is wrong.  I don't know if that's a
    >> deficiency in my code or in the era data itself.
    >
    > The date is actually correct. This is why I wanted to know the
    > method of getting an era's beginning date, because eras, unlike
    > years, months, and days, can begin and end at any time on a calendar.
    >
    > In the case of the Japanese calendar, the 235th era is indeed the
    > Heisei era, but since you didn't specify year & date components,
    > NSCalendar assumes you meant the first year/month/day in that time
    > frame. The first year of the Heisei era is 1989, but January 1, 1989
    > is actually in the Showa (234th) era.

    I guess I shouldn't have said "wrong", but rather "not what we
    wanted." =)  With a bit more experimentation, I established that Mac
    OS does in fact know the precise date of the era change -- getting the
    era for January 8, 1989 tells me 235 (Heisei), but for January 7, it's
    234 (Showa).  How to get NSCalendar (or whoever) to return that date,
    however, escapes me.

    --Chris Nebel
  • On Jan 28, 2008, at 3:49 PM, Nick Zitzmann wrote:

    > What's the best way of getting the start date for a given era in an
    > NSCalendar?
    >
    > For days, weeks, etc. this is trivial, since they have a universal
    > start time. But an era can begin and end at any point in time.
    > These points in time are trivial to figure out on the Gregorian
    > calendar (the AD era began on January 1, 1), but the Japanese
    > calendar is a totally different story (the Heisei era began on
    > January 7, 1989 for example).
    >
    > I've tried to solve this by polling NSCalendar for era changes, by
    > getting the date for the first day in the era (which may not
    > actually be in the era) and stepping through days until the era of
    > the day matches the desired era, but this takes way too long to
    > calculate for all eras on the Japanese calendar, so I'm hoping
    > there's a better way.

    In 10.5 and later, there is the new -
    rangeOfUnit:startDate:interval:forDate: method in NSCalendar for just
    this sort of thing.

    #import <Foundation/Foundation.h>

    int main() {
    [NSAutoreleasePool new];
    id cal = [[[NSCalendar alloc]
    initWithCalendarIdentifier:NSJapaneseCalendar] autorelease];
    NSDate *date = nil;
    NSTimeInterval ti = 0.0;
    BOOL b = [cal rangeOfUnit:NSEraCalendarUnit startDate:&date
    interval:&ti forDate:[NSDate date]];
    NSLog(@"Start date is '%@', interval is %f, succeeded? %s", date,
    ti, b ? "yes" : "no");
    return 0;
    }

    % cc test.m -framework Foundation
    % ./a.out
    2008-02-01 09:48:17.115 a.out[38611:10b] Start date is '1989-01-08
    00:00:00 -0800', interval is 2019686400.000000, succeeded? yes
    %

    Though note that the time zone there is a little funky.  Could be an
    issue with date display, or with the computation/database not taking
    the time zone into account, or with it actually taking it into
    account when I wasn't expecting it to.  Of course, that raises the
    interesting question of whether the era did begin on that date (in
    the Gregorian calendar) at midnight GMT+0, or whether midnight in
    Tokyo would be a better answer, in which case the answer is about 17
    hours off.

    If I set the time zone of the calendar for calculation purposes to :
    [cal setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Tokyo"]];

    Then the answer is:

    2008-02-01 10:03:24.325 a.out[38637:10b] Start date is '1989-01-07
    07:00:00 -0800', interval is 2019686400.000000, succeeded? yes

    (when displayed in the Gregorian calendar in my default time zone,
    GMT-0800).

    How does NSCalendar do this?  You'd never guess.  It gets close, then
    "steps through days until the era of the day matches the desired
    era".  The actual era database is buried in the ICU library and isn't
    readily accessible.

    > takes way too long [...]

    One way to handle this with calendrical walking forward/backward
    algorithms is binary search: with a date starting in the previous
    era, pick a k > 0, and try adding 2^k seconds; if that puts you in
    the next era, you've overshot, decrement k and start over; if the new
    date is still in the previous era, set that to be your current date,
    decrement k, and start over; until you overshoot when k = 0.  As long
    as k starts sufficiently large, you will never successfully need to
    add each 2^k more than once, or you would have succeeded on the
    previous iteration when k was one larger (2 * 2^k == 2^(k+1)), and so
    you can decrement k on each iteration.  Starting around k = 37 is
    usually plenty, so you'd have up to ~37 probes.

    Chris Kane
    Cocoa Frameworks, Apple
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today