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..?
Printable View
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..?
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
Or something :)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)
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?
Here's a good start, Note it uses the leap year approximation method see http://en.wikipedia.org/wiki/Leap_year
All you have to do is make it pretty, add weeks and days then do whatever with the timestamp.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;
}
If the week is 47 then it'll be,
Or something, I don't know -- I don't like time :)Code:weeksInDays = 47 * 7
daysSinceStartOfYear = weeksInDays - (7 - dayOfWeek)
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
Well I was sortof on track :)
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!
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.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;
--
Mats
Thanks to you both! I'll have a look at the code.
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.
Make sure you pick some weird dates in that case, such as 29Feb on a leap year, or some other weird ones.
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! :D
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?
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. ;)Quote:
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.
The text in the barcode is printed below the code, and should be readable for mortals.. hex is not readable for mortals. It's a good suggestion though..
In my opinion, the best solution would be YDDD.