Thread: Help on converting date

  1. #1
    Registered User
    Join Date
    Feb 2002
    Posts
    329

    Help on converting date

    I have a date on the format YWWD, where:
    Y=year
    WW=week number of year
    D=day of week

    Anyone have a clue on how to convert this to a regular date(CCYY-MM-DD)?
    Can't find any functions for this in C..?

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Convert the original format into a unix timestamp, ie seconds since 1970, Then use the C standard time.h functions to convert it into the new format.

    ie
    Code:
    SECONDSINAYEAR=365.25 * (24 * pow(60, 2))
    SECONDSINAWEEK=7 * (24 * pow(60, 2))
    
    year = 2000
    ww = 24
    d = 5
    
    yearOffset = year - 1970
    // etc for weeks / days
    
    secondsSinceEpoch = (yearsOffset * SECONDSINAYEAR) + (weekOffset * SECONDSINAWEEK)
    Or something
    Last edited by zacs7; 10-12-2007 at 04:50 AM.

  3. #3
    Registered User
    Join Date
    Feb 2002
    Posts
    329
    How do i converet 7403(2007, week number 40, wednesday) to a unix time?

    Edit:
    Some years start with week number 53

    Or to put it another way:
    How do i get the week number of 01. january of a year?
    Last edited by knutso; 10-12-2007 at 05:03 AM.

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Here's a good start, Note it uses the leap year approximation method see http://en.wikipedia.org/wiki/Leap_year
    Code:
    time_t makeTimestamp(int year, int week, int day)
    {
        time_t secs = 0;
        int daysPerYear = 365;
        
        /* if it's a leap year give it 366 days */
        if(isLeapYear(year) != 0)
            daysPerYear = 366;
        
        /* add the years in seconds from 1970 */
        secs += (year - 1970) * (daysPerYear * (24 * (60 * 60)));
        
        /* add the weeks, etc */
        
        return secs;
    }
    
    /* returns non-zero if the year is a leap year */
    int isLeapYear(int year)
    {
        if(year % 400 == 0 || year % 4 == 0)
            return 0;       /* leap */
        else if(year % 100 == 0)
            return 1;       /* not a leap */
        return 2;
    }
    All you have to do is make it pretty, add weeks and days then do whatever with the timestamp.

    If the week is 47 then it'll be,
    Code:
    weeksInDays = 47 * 7
    daysSinceStartOfYear = weeksInDays - (7 - dayOfWeek)
    Or something, I don't know -- I don't like time
    Last edited by zacs7; 10-12-2007 at 05:10 AM.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    OK, so the first question is "what is the definition of a workweek". You need to know which week is "week 1" and at what date that week starts, since, as you say, some years end with a week 53 that overlaps into the next year.

    Once you know which date week one starts, you then add the number of days that your 40 weeks (40 * 7 = 280 days), combined with the day within the week.

    Add the number of days to the "start of week 1 date", and you've got a date.

    Since UNIX time is "seconds since 1 Jan 1970", you multiply the number of days by 24 * 60 * 60 and you get the number of seconds into the year.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Well I was sortof on track

  7. #7
    Registered User
    Join Date
    Feb 2002
    Posts
    329
    So is there a function like: weeknumber('2007.01.01');?

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by knutso View Post
    So is there a function like: weeknumber('2007.01.01');?
    I'm not aware of a "commonly available" one like that. It's not helped much by different countries having different definitions of "week number".

    I wrote something to solve this a long time ago, which works out the day of December 31st of previous year, (because if it's before wednesday, the first week is week 53, otherwise week 1), then calculates the week number by calculating number of days between week 1 and the "wanted" date. This was quite a while ago, and I had a quick look to see if I could find it, but I wasn't able to find it right now... [It would be in Pascal anyways, so you would have to convert the algorithm to C].

    Edit: Found it!
    Code:
    FUNCTION WeekNumber{date: String[h]): WORD};
    
      VAR
        day,
        month,
        year:        WORD;
        firstOf:     INTEGER;
        dayNum:      INTEGER;
        dayIntoYear: INTEGER;
        firstMonday: INTEGER;
    
      FUNCTION FirstMondayInYear(y: WORD): INTEGER;
    
        (* This calculates the Monday of Week 1 of the year we are
           interested in, which actually may be the in the previous
           year, since that week may begin in December. *)
    
        VAR
          x:    INTEGER;
          d:    WORD;
          step: INTEGER;
    
        BEGIN
          x := CalcDayNum(y, 1, 1);
          d := WeekDayNum(x);
          IF d < Thursday THEN
            step := -1
          ELSE
            step := 1;
          WHILE d <> Monday DO BEGIN
            x := x + step;
            d := WeekDayNum(x);
          END;
          FirstMondayInYear := x;
        END;
    
    
      FUNCTION CalcWeekNumber(year, month, day: WORD): WORD;
    
        BEGIN
          firstMonday := FirstMondayInYear(year);
          firstOf := CalcDayNum(year, 1, 1);
          dayNum := CalcDayNum(year, month, day);
          IF dayNum < firstMonday THEN
            CalcWeekNumber := CalcWeekNumber(year-1, 12, 31)
          ELSE BEGIN
            IF dayNum >= FirstMondayInYear(year+1) THEN
              CalcWeekNumber := CalcWeekNumber(year+1, 1, 1)
            ELSE
              CalcWeekNumber := (dayNum - firstMonday) DIV 7 + 1;
          END;
        END;
    
    
      BEGIN
        SplitDate(date, year, month, day);
        WeekNumber := CalcWeekNumber(year, month, day);
      END;
    Edit2: That is missing a few crucial functions. The CalcDayNum() is basicily a integer representing the number of days from a set date (such as 1 Jan 1970). Likewise, we need a function to figure out what day of the week a certain date is - there's a post recently that does that, or you can use the standard C time functions to get the day of week from a "time_t" type.

    --
    Mats
    Last edited by matsp; 10-12-2007 at 05:59 AM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Feb 2002
    Posts
    329
    Thanks to you both! I'll have a look at the code.

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I hope you've got a number of sample input dates and their correct outputs to use as test cases. This is something that would very much bennefit from having some unit tests, and it would be very easy to test also.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Make sure you pick some weird dates in that case, such as 29Feb on a leap year, or some other weird ones.

  12. #12
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Where on earth did you find such a weird date format anyways?
    I've seen strange date formatting on mainframes, but that one definitely takes the cake!

  13. #13
    Registered User
    Join Date
    Feb 2002
    Posts
    329
    The date format is from a lotnumber in a barcode, hence it has to be as short as possible.
    I converted the functions to c, but i'm not entirely finished yet..I'll post it here when it's finished?

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by knutso View Post
    The date format is from a lotnumber in a barcode, hence it has to be as short as possible.
    In that case, I don't know why they didn't simply replace WWD with the 3-digit number for the day of the year since it's the same length.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    In that case, I don't know why they didn't simply replace WWD with the 3-digit number for the day of the year since it's the same length.
    Or they could use a 4 digit hex number that represents the number of days since 1970 -- that should be good until around the year 2149.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Advancing day by day until it matches a second date
    By nhubred in forum C++ Programming
    Replies: 1
    Last Post: 05-30-2009, 08:55 AM
  2. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  3. converting 64 bit time and date
    By pastitprogram in forum C++ Programming
    Replies: 29
    Last Post: 07-02-2008, 03:53 PM
  4. CDate Class - handle date manipulation simply
    By LuckY in forum C++ Programming
    Replies: 5
    Last Post: 07-16-2003, 08:35 AM