views:

380

answers:

1

I need to write a function that converts a Julian dates (Year, Day of Year, Hour of Day and Minutes) into a standard form (Year, Month, Day of Month, Hour of Day and Minutes) and express it as a string. I figure there's got to be someone who's already written a library or component which can do the conversion from Day Of Year to Month and Day of Month. I've looked at several well-known datetime libraries:

  • ctime - Specifically using a tm struct and mktime(tm *timeptr) as this generally sets the values of the tm struct to the appropriate places except that "The original values of the members tm_wday and tm_yday of timeptr are ignored..." which doesn't help.
  • Boost::DateTime - Gregorian is constructed date(greg_year, greg_month, greg_day) which doesn't help. However, they do have a date_from_tm(tm datetm) but "The fields: tm_wday , tm_yday , tm_hour, tm_min, tm_sec, and tm_isdst are ignored." Again, no help.
  • COleDateTime - This project contains COM so why not? The COleDateTime constructor COleDateTime( int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec ) doesn't help. And I don't see any other conversion functions to go with it.

As you can see, these all need Month and Day of Month which is exactly what I'm trying to avoid in the first place. I must be either missing something or haven't looked in the right places (not perfect, as much as I try.)

Anyone can help? I'd prefer to avoid writing my own as there's almost always bound to be some gotcha I miss.

+1  A: 

It seems easy to compute the month and day of month from the day of year. This should do it:

static const int month_len[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

int leap = (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
int day_of_month = day_of_year;
int month;
for (month = 0; month < 12; month ++) {
    int mlen = month_len[month];
    if (leap && month == 1)
        mlen ++;
    if (day_of_month <= mlen)
        break;
    day_of_month -= mlen;
}

Note that this computes the month starting with zero for January, but assumes that day counts (either day of year or day of month) start at one. If the day of year count is invalid (beyond the end of the year) then the resulting month value is 12 (the "month after December").

"Julian" is a source of confusion, since it also stands for the "Julian calendar" which differs from the Gregorian calendar by a few dozen days, and the computation of leap years. Here I just assumed that you just wanted to convert a "day of year" count into a "month and day of month" within the context of a given, Gregorian year.

Thomas Pornin
Thank you for your post. I'm really looking to see if there's a library which can handle these types of dates and conversions between them. I've got something written which follows along the same lines but I always feel better when it's been vetted by a group.
wheaties