616Free software code to convert ISO calendar dates to ISO Week Date and back.
- Mar 1, 2003The challenge, find a faster and shorter solution. Word document included in attachment.
The split week at the end of the year creates the problem. 2003-12-29 will be the first day of first week in 2004, 2004-W01-1. January dates also switch years.
The ISO standard puts days in a different week year than the calendar year.
| 28 | 29 | 30 | 31 | 01 | 02 | 03 | January dates are part of the previous year.
| 29 | 30 | 31 | 01 | 02 | 03 | 04 | December dates are part of the following years.
Converting from Week dates to Calendar dates is simple. The conversion from Calendar dates to Week dates is difficult.
Most computers have a method of converting calendar date to integer number of days.
You can use the Julian days in C in the DATLIB library. I customized my own to for internal format YYYYMMDDhhmmssffffffffffff necessary for Universal Time offset conversion and fractions of seconds.
Function #JDN@DAT convert a Calendar Date to Julian Day
Function @DAT#JND converts a Julian Day to a Calendar Date
Julian Days are integer days starting from using Proleptic calendars 4712 -01-01 BC Julian, 4713-11-24 BC Gregorian. 2003-01-01 is 245,261days after the first day. The formulas are on the Internet under Julian Days (not Julian Date) copies included at the end of the report.
This are free for personal or use. Calculations must be integers, unless stated otherwise.
Get Julian day for current calendar day.
Eval cljd# = #JDN@DAT(cldt)
Get day of week %INT makes sure intermediate values are whole number, no decimals fractions
Eval dow# = (cljd# - (%INT((cljd#/7) * 7) + 1
Convert to decimal
Eval wkdk# = dow#
Get the first day of the week for the calendar date.
Eval cljd# = cljd# - dow# + 1
Get year of week, Most days OK Convert to decmal.
Eval wkyy# = clyy#
If clmd# < 0104 or clmd# > 1228
Execute subroutine for exceptions
Determine first day of week first week.
Eval wkjd# = #JDN@DAT( whyy + '-01-04')
Eval dow# = (wkjd# - (%INT((wkjd#/7) * 7) + 1
Eval wkjd# = wkjd# - dow# +1
Get week of year
Difference of days between calendar first day of week and first day of first week
Eval woy# = %int(cljd# - wkjd#)/7) -1
Convert to decimal
Eval wkyr# = woy#
Subroutine of exceptions
If clmd# < 0104
If last half of the week
If wkdw# > 4
Eval wkyy# = cly# -1
If first day is first half of the week
If wkdw# < 1
and (clmd# > 1228
or clmd# > 1229
or clmd# > 1230)
Eval wkyy# = clyy# +1
Convert Week date to Calendar date.
Determine first day of first week
Eval wkjd# = #JDN@DAT(wkyy + -01:04')
Determine day of week
Eval dow# = (wkjd# - (%INT(wkjd#/7) * 7)) +1
Get first day of week
Eval wkjd# = wkjd# - dow#
Get Calendar Julian days , convert weeks to days and add day of week
Eval cljd# = wkjd# + (wkww# -1) * 7 ) +1 + wkdw#
Get Calendar Date from Julian Date
Eval cldt = @dat#JDN)cljd#)
In 1968 in a letter to the editor of Communications of the ACM (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel and Thomas C. Van Flandern presented computational algorithms to convert between Julian day numbers and Gregorian dates.
The Julian day (jd) is computed from Gregorian day, month and year (d, m, y) as follows:
jd = ( 1461 * ( y + 4800 + ( m - 14 ) / 12 ) ) / 4 +
( 367 * ( m - 2 - 12 * ( ( m - 14 ) / 12 ) ) ) / 12 -
( 3 * ( ( y + 4900 + ( m - 14 ) / 12 ) / 100 ) ) / 4 +
d - 32075
Division is to be understood as in integer arithmetic, with the remainders discarded (use INT with division).
Converting from the Julian day to the Gregorian day is performed thus:
l = jd + 68569
n = ( 4 * l ) / 146097
l = l - ( 146097 * n + 3 ) / 4
i = ( 4000 * ( l + 1 ) ) / 1461001 (that's 1,461,001)
l = l - ( 1461 * i ) / 4 + 31
j = ( 80 * l ) / 2447
d = l - ( 2447 * j ) / 80
l = j / 11
m = j + 2 - ( 12 * l )
y = 100 * ( n - 49 ) + i + l (that's a lower-case L)