I'm forwarding this message from John Dlugosz, who is not on the time zone mailing list. Those of you who are on the list, please direct replies appropriately. --ado From: John Dlugosz [mailto:JDlugosz@TradeStation.com] Sent: Thursday, January 15, 2009 12:40 To: tz@lecserver.nci.nih.gov Subject: Notes on 'timesub" The implementation of 'timesub' uses quite a bit of complex logic, approximations, and looping to do what can be done with a single expression. The part of the function that digests the number of days into y/m/d fields has been known since before computers as "Julian Day Number" and that can be harnessed directly simply by subtracting a constant for the Epoch base. Here is my version, which is not so digested into my own library that you can't follow the logic: void timezone_t::state::timesub ( const __time64_t t, // input time number const long offset, // added to time, but figures date from original (e.g. like a denormal value) ymd_hms& tmp // output ) const { // more complex than it needs to be! static const int JDayEpoch= Julian_day_number (ymd(EPOCH_YEAR, 1, 1)); int days_in_epoch = t / SECSPERDAY; int rem = t - days_in_epoch * SECSPERDAY; int corr= count_leap_seconds (JDayEpoch, JDayEpoch+days_in_epoch); tmp= Julian_day_number (JDayEpoch+days_in_epoch); tmp.set_normalized (hms(0,0,rem+offset - corr)); } In your code, the part I'm referring to is the middle. First it finds 'corr' for leap seconds, and afterwards it adds the seconds into the h/m/s possibly overflowing into the d/m/y. I have those in callable functions, but the approach is the same. It's just that the middle part, converting a number of seconds into y/m/d, is not as hard as you make it out to be. This is a direct implementation of the published formula, which involves no looping or successive approximations or peeling off each month individually: ymd Julian_day_number (int J) { const int j= J+32044; const int g= j / 146097; const int dg= j % 146097; const int c= (dg / 36524 + 1) * 3 / 4; const int dc= dg - c * 36524; const int b= dc / 1461; const int db= dc % 1461; const int a= (db/365+1) * 3 / 4; const int da= db - a * 365; const int y= g*400 + c*100 + b*4 + a; const int m= (da*5+308) / 153 - 2; const int d= da - (m+4) *153 / 5 + 122; return ymd (y-4800+(m+2)/12, (m+2)%12+1, d+1); } (The comment that it is (still) more complex than it needs to be is because the normalization code in my library can handle that directly, so I can just call existing code.) --John
participants (1)
-
Olson, Arthur David (NIH/NCI) [E]