Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is there a macro or package to calculate the ISO week number or alternative can someone help me with one?

share|improve this question
add comment

3 Answers

up vote 12 down vote accepted

There is no package as such, but Taco Hoekwater, wrote a macro called calendarweek that you can use. You find it on CTAN at weekday.

Here is a minimal example, as to how to use it:

\documentclass{article}
%% calendarweek.tex
%% 2006 (C) Taco Hoekwater, public domain
%% Watch out: Dec 29 can be week 1 of the next year; and Jan 3 can be
%% week 53 of the previous year.

\def\Expr#1{\the\numexpr #1\relax}

\def\Modulonumber#1#2{\Expr{#2-((((#2+(#1/2))/#1)-1)*#1)}}
\def\Divisionnumber#1#2{\Expr{(2*#2-#1)/(2*#1)}}

\def\Mod#1#2{\Modulonumber{\Expr{#2}}{\Expr{#1}}}
\def\Div#1#2{\Divisionnumber{\Expr{#2}}{\Expr{#1}}}

\def\Jday#1#2#3%
    {\Expr{#1+\Div{((153*(\Expr{#2+(12*(\Div{14-#2}{12}))-3}))+2)}
     {5}+365*(\Expr{#3+4800-(\Div{14-#2}{12})})+
      (\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{4})-
      (\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{100})+
      (\Div{\Expr{#3+4800-(\Div{14-#2}{12})}}{400})-32045 }}

\def\cwhlp#1#2#3%
    {\Expr{\Mod {\Mod {\Mod {\Expr
     {\Jday{#1}{#2}{#3}+31741-\Mod{\Jday{#1}{#2}{#3}}{7}}}%
     {146097}}{36524}}{1461}}}

\def\calendarweek#1#2#3%
  {\Expr{\Expr{\Div{\Expr{\Mod{\cwhlp{#1}{#2}{#3}-
    \Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}{365}+
         \Expr{\Div{\cwhlp{#1}{#2}{#3}}{1460}}}}{7} +1}}}

\begin{document}

\calendarweek{28}{2}{2011}

\end{document}
share|improve this answer
add comment

Here is expl3:

\documentclass{minimal}

\usepackage{expl3}

\ExplSyntaxOn

%% http://www.tondering.dk/claus/cal/week.php#calcweekno
\int_new:N \l_week_number_year_int
\int_new:N \l_week_number_month_int
\int_new:N \l_week_number_day_int
\int_new:N \l_week_number_a_int
\int_new:N \l_week_number_b_int
\int_new:N \l_week_number_c_int
\int_new:N \l_week_number_s_int
\int_new:N \l_week_number_e_int
\int_new:N \l_week_number_f_int
\int_new:N \l_week_number_g_int
\int_new:N \l_week_number_d_int
\int_new:N \l_week_number_n_int
\int_new:N \l_week_number_W_int

\cs_new:Nn \week_number:nnn {

  \int_set:Nn \l_week_number_year_int { #1 }
  \int_set:Nn \l_week_number_month_int { #2 }
  \int_set:Nn \l_week_number_day_int { #3 }

  \int_compare:nNnTF { \l_week_number_month_int } < { 3 } % jan or feb
  { % true

    \int_set:Nn \l_week_number_a_int { \l_week_number_year_int - 1 }

    \int_set:Nn \l_week_number_b_int {
      \int_div_truncate:nn { \l_week_number_a_int } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int } { 400 }
    }

    \int_set:Nn \l_week_number_c_int {
      \int_div_truncate:nn { \l_week_number_a_int - 1 } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int - 1 } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int - 1 } { 400 }
    }

    \int_set:Nn \l_week_number_s_int {
      \l_week_number_b_int - \l_week_number_c_int }

    \int_zero:N \l_week_number_e_int

    \int_set:Nn \l_week_number_f_int { \l_week_number_day_int - 1
      + 31 * ( \l_week_number_month_int - 1 ) }

  } % end true
  { % false

    \int_set_eq:NN \l_week_number_a_int \l_week_number_year_int

    \int_set:Nn \l_week_number_b_int {
      \int_div_truncate:nn { \l_week_number_a_int } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int } { 400 }
    }

    \int_set:Nn \l_week_number_c_int {
      \int_div_truncate:nn { \l_week_number_a_int - 1 } { 4 }
      - \int_div_truncate:nn { \l_week_number_a_int - 1 } { 100 }
      + \int_div_truncate:nn { \l_week_number_a_int - 1 } { 400 }
    }

    \int_set:Nn \l_week_number_s_int {
      \l_week_number_b_int - \l_week_number_c_int }

    \int_set:Nn \l_week_number_e_int { \l_week_number_s_int + 1 }

    \int_set:Nn \l_week_number_f_int { \l_week_number_day_int
      + \int_div_truncate:nn {
        153 * ( \l_week_number_month_int - 3 ) + 2 } { 5 }
      + 58 + \l_week_number_s_int }

  } % end false

  \int_set:Nn \l_week_number_g_int {
    \int_mod:nn { \l_week_number_a_int + \l_week_number_b_int } { 7 }  }

  \int_set:Nn \l_week_number_d_int {
    \int_mod:nn { \l_week_number_f_int + \l_week_number_g_int
      - \l_week_number_e_int } { 7 }  }

  \int_set:Nn \l_week_number_n_int {
    \l_week_number_f_int + 3 - \l_week_number_d_int }

  \int_compare:nNnTF { \l_week_number_n_int } < { 0 }
  { %true

    \int_set:Nn \l_week_number_W_int { 53
      - \int_div_truncate:nn { \l_week_number_g_int
        - \l_week_number_s_int } { 5 } }

  } % end true
  { % false

    \int_compare:nNnTF { \l_week_number_n_int } > { 364
      + \l_week_number_s_int }
    { % true

      \int_set:Nn \l_week_number_W_int { 1 }

    } % end true
    { % false

      \int_set:Nn \l_week_number_W_int { \int_div_truncate:nn {
          \l_week_number_n_int } { 7 } + 1 }

    } % end false

  } % end false

}
\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn
\week_number:nnn { 2010 } { 01 } { 01 }
\int_to_arabic:n { \l_week_number_W_int }
\ExplSyntaxOff

\end{document}
share|improve this answer
add comment

Just an idea:

The datenumber package can give you the day as number. By subtracting the number of Jan 1st of the same year and adding one you can get the day of the year. The number of the week is then about this number divided by seven.

Because ISO weeks start by definition with a Monday you have to add an offset:

[ISO week number] = 
 floor( ( [number of selected date] - [number of first Monday of the year] + 1 ) / 7 ) + 1 

The package also gives you the possibility to check the day of the week, which allows you to find the first Monday of the year.

I'm not sure if I understood ISO week numbers correctly and I might be off with the equations (it's 1.30am), but you get the idea.

share|improve this answer
    
The ISO week number starts with a Thursday! So some months can have 5 weeks and others 4. It is a somewhat convoluted scheme. Thanks for the answer though. –  Yiannis Lazarides Feb 13 '11 at 1:42
1  
@saltypen: The Wikipedia article you linked states: "Weeks start with Monday". Ok, I see now: "Week 1 := the week with the year's first Thursday in it (the ISO 8601 definition)". But the principle is the same! –  Martin Scharrer Feb 13 '11 at 1:47
    
Thanks, but how do I determine the first Thursday of the year? –  Yiannis Lazarides Feb 18 '11 at 7:45
    
@saltypen: The package gives you the day-of-the-week as number in datedayname Mo=1,Su=7 => Thu=5. You look which day-of-the-week the 1.1. is, then you simply calculate (5 - weekday(1.1.) ) modulo 7. The result is the number of days you have to add to 1.1. to get to the first Thursday. –  Martin Scharrer Feb 18 '11 at 8:25
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.