Tuesday, July 21, 2009

Long to Datetime

I'm absolutely stuck on this one calculation. Everything else is working perfectly. I can't figure out how to calculate the calendar given a long "number of business days" since 1970. The funny thing is, I figured it out fine going the other way (that is, datetime to long). Something is fishy in my calculations (I've tested the test numbers again and again).

Also, since you suggested using smaller structs (since femtosecond has no need of knowing month, etc), I started using ymdstruct (year, month, day structs) and hmsstruct (hour, minute, second structs). Send a long "number of days" to long_to_ymdstruct() or "number of seconds" to long_to_hmsstruct() and the function will return the appropriate struct. So to calculate a calendar date, it's just a matter of converting given frequency to days or seconds (depending on precision of frequencies... for the Business Day case, we need to convert to days by using the ymdstruct).

I may be overly complicating things. I'm not totally confident in the efficiency of structs in C (I know you should try to have structs contain a base two number of items so the compiler can do a cheap shift instead of an expensive multiplication to find members). Unfortunately, both ymdstruct and hmsstruct seem like unnecessary baggage for the long_to_datestruct function, since this function returns neither a ymdstruct nor an hmsstruct (it returns a datestruct, which is a seperate struct entirely...). There really has to be a better way of doing this... I just haven't thought of it yet...

But regardless, I still can't figure out these business day calculations. The most annoying part of the entire endeavor is that January 1, 1970 is on a Thursday... So I know I have to add some offset or subtract some other offset... but what are they? The closest calculation I could try to find (remember, I'm only trying to turn business days into absolute days to fill my ymdstruct):

absdays = 7 * (dlong / 5) + dlong % 5

where dlong is the long long value representing a date and absdays are the absolute number of days (since Jan 1, 1970, specifically).

4 comments:

  1. have you looked at the frequency conversion code in scikits.timeseries? specifically line 602 in c_dates.c

    return ((fromDate-1)/5)*7 + (fromDate-1)%5 + 1;

    it's been a while since I looked at this code, but I'm pretty sure it is based on days since 0AD.

    ReplyDelete
  2. That's EXACTLY what my final calculations looked like, Matt. I looked around the TimeSeries Code, but didn't find them as fast as I'd hoped for, so I gave up. Thanks for the input.

    ReplyDelete
  3. There *is* no 0AD, the calender starts at 1AD. And don't forget the switch from the Julian calender to the Gregorian calender on 15 October 1582 ;)

    ReplyDelete
  4. I guess the Julian to Gregorian calendar change happened on different dates for different countries (http://www.searchforancestors.com/utility/gregorian.html). cal on this machine shows a change on September 3, 1752. My current code completely ignores the calendar change and pretends it never happened...

    ReplyDelete