Loading ...
Sorry, an error occurred while loading the content.

616Free software code to convert ISO calendar dates to ISO Week Date and back.

Expand Messages
  • hjwoudenberg@aol.com
    Mar 1, 2003
      The 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
      Exsr excyrsr
      End

      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
      excyrsr Begsr
      If clmd# < 0104
      If last half of the week
      If wkdw# > 4
      Eval wkyy# = cly# -1
      Else
      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
      End


      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)