ロゴ(青) ロゴ(緑)

Tips20: WEEKNUM関数 と ISO8601:週番号  

  (初版 : 2010/3/14  ,  英訳 初版 : 2014/8/10 )
(日本語 & 英語 第2版 : 2015/7/10 )
( JavaScript 移植 : 2021/2/13 )
--- ISO8601 週番号 関数式 ----
( a ) Frank Kabel 氏による Excel 関数式    ( JavaScript コード )
( b ) Barry Houdini 氏による Excel 関数式    ( JavaScript コード )


「1年の始めから通しの週番号(1〜54)」は Excel の 分析ツールにある WEEKNUM 関数で計算
できます。なお、第2引数で、「週の始め」に日曜日/月曜日の2パターンが指定できます。

ただし、この関数は1月1日を【第1週】として処理している為、年末の最終週(第52 〜 54週)と年
初の第1週の日数が「1〜7日間」の間で変動します(後述のテストブックを参照)。

国際標準として ISO8601:週番号 で規定されている計算方法があります。
      ・週は月曜日から始まる。
      ・「1月の第1木曜日が含まれる週」の7日間が、その年の第1週です。
        もしくは、「1月4日が含まれる週が、その年の第1週」とも表現します。この2つの表現は同義
        です(これは、年末〜年初の境界の週については、過半数の4日間以上が属する『年』の方
        に、その週の7日間全てが属するという意味です)。
      ・全ての週は「7日間」です(ExcelのWEEKNUM関数のように、7日に満たない週が表れる事
        はありません)。

      補足 : ISO標準の定義は【月曜 始まり】のみですが、日本での1週間は【日曜 始まり】
               で考える方が多いでしょう。ISO標準と同様の基準で『日曜 始まり』の週番号を
               構築する事が出来ます(後述)。その場合には、【第1水曜日が含まれる週が、
               その年の第1週】となりますが、【1月4日が含まれる週が、その年の第1週】とい
               う点は変わりません。

残念ながら、Excel の WEEKNUM関数は、この[ ISO8601:週番号] をサポートしていません。
(2013/1/10 追記)
      Excel2010 から、WEEKNUM関数の 「第2 引数:週の基準」 に 21 を指定すると、[ISO8601:週番号] を取得
      できるようになりました( WEEKNUM 関数 ヘルプ )。
            =WEEKNUM ( 日付 , 21 )
(2013/3/31 追記)
      Excel2013 から、[ISO8601:週番号] 専用の関数 ( ISOWEEKNUM ) が追加されました。
      尚、Excel2013 の WEEKNUM でも 引き続き 第2引数に 21 を指定すれば ISO週番号を取得できます。


[ この場所へのリンク ]

参考 : MSDN:Excel2007での週番号システムと日付/時刻表示の実装

上記文書には、Excel にて [ ISO8601:週番号 ] を計算する方法が紹介されています。
  (1) Frank Kabel 氏による算出式(A1 に日付)
          [月曜 始まり]
          =INT((A1-DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3)
                  +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3))+5)/7)

  (2) 上記文書には載っていませんが、VBA の DatePart/Format関数では [ ISO8601:週番号 ] を
      サポートしています(下記の引数指定による)。
            週番号 = DatePart ( "ww", 日付, vbMonday, vbFirstFourDays )
            週番号 = CInt( Format ( 日付, "ww", vbMonday, vbFirstFourDays ) )
      第3引数を vbSunday にすると、「日曜日始まりの週」の週番号が計算できます。

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
アドインが使えない場合に対処する為の、Excel/WEEKNUM関数(分析ツールアドイン)の代替式も
上記文書で紹介されています(なお、下記 (3)(4) は ISO8601週番号 ではありません。WEEKNUM
関数の代替です)。
  (3) Daniel Maher 氏による算出式(A1 に日付)
          [月曜 始まり]
          =1+INT((B4-(DATE(YEAR(B4),1,2)-WEEKDAY(DATE(YEAR(B4),1,0))))/7)
          [日曜 始まり]
          =1+INT((A1-(DATE(YEAR(A1),1,2)-WEEKDAY(DATE(YEAR(A1),1,1))))/7)

  (4) VBA の Format関数を利用したユーザー定義関数
          Function VBAWeekNum(D As Date, FWDayArg As Integer) As Integer
              VBAWeekNum = CInt(Format(D, "ww", FWDayArg))
          End Function

    (2010/3/14 16:00 訂正)
    当初、上記 (3)(4) を 『[ ISO8601 週番号 ] 算出式の紹介』 と勘違いして、『テストの結果、その計算は間違っている』
    と解説していましたが、それは誤りです。上記 (3)(4) は Excel/WEEKNUM関数の代替式であり、その計算結果は
    WEEKNUM関数と同じであり、計算間違いはありません。

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
各々の計算を確認してみたところ、
    ・ (2) VBAの Format関数 および DatePart関数による [ ISO8601週番号 ] 算出式
では、最終週 と 第1週 の部分で誤った結果を出す場合がありました。
  [ KB 200299 ] BUG: Format or DatePart Functions Can Return Wrong Week Number for Last Monday in Year ( リンク切れ )
  Microsoft Docs : Format or DatePart functions can return wrong week number for last Monday in Year

    [ テストブック : ISO8601_WEEKNUM.xls ]   ( 2010/3/16 15:00 更新 )
      (注 : WEEKNUM関数を使っているので分析ツールをアドイン登録してから開いてください。
              Excel2007以降ではアドイン登録しなくてもWEEKNUM関数が使えます)

テストブック、および、OpenOffice.org Calc によるテストで、『Frank Kabel 氏による算出式』は
正しい週番号を計算している
事を確認しました。



[ この場所へのリンク ]

Frank Kabel 氏による算出式は【月曜 始まり】しかありませんので、この式を加工して【日曜 始まり】
の週番号を得る式を作成してみます。

    [月曜 始まり]
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3))+5)/7)

この式は 『日[1], 月[2] ・・・ 土[7] 』 という
    ・ 『日曜 始まりの曜日番号』を使い
    ・ 【月曜 始まりの週番号】を算出
しています。先ずは、『月曜 始まりの曜日番号』を使って【月曜 始まりの週番号】を算出するよう
に加工します。

ここで、WEEKDAY(日付-1, 1)とすると、WEEKDAY( ,1) で『月[1]・・・土[6],日[7]』が表現できます。
逆に、WEEKDAY(日付+1, 2)とすれば、WEEKDAY( ,2) で『日[1],月[2]・・・土[7]』が表現できます。

この変換を使って上記式を月曜始まりの曜日番号で表現するように変えてみます。

    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1-1)+4),1,3))+5)/7)
        ↓
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1-1+1, 2)+4),1,3)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1-1+1, 2)+4),1,3)+1, 2)+5)/7)
        ↓
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1, 2)+4),1,3)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1, 2)+4),1,3)+1, 2)+5)/7)
           『月曜 始まりの曜日番号』を使って【月曜 始まりの週番号】を算出

  後述で私が整理した結果、下記式も上記と同じ意味・結果となります。
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1, 2)+4),1,4)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1, 2)+4),1,4), 2)+6)/7)

  また、後述barry houdini 氏による下記式でも同じ結果が得られます。 (2015/7/10 追加)
    =INT((A1-WEEKDAY(A1, 2)-DATE(YEAR(A1-WEEKDAY(A1, 2)+4),1,4))/7)+2
          初出:2006年5月16日 MrExcel.com / Year-Week Number


最後の式で、曜日番号を日曜始まり[ WEEKDAY( ,1) ]に変えてやると【日曜始まり】の週番号が
得られます。
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1, 1)+4),1,3)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1, 1)+4),1,3)+1, 1)+5)/7)
           『日曜 始まりの曜日番号』を使って【日曜 始まりの週番号】を算出

  後述で私が整理した結果、下記式も上記と同じ意味・結果となります。
    =INT((A1-DATE(YEAR(A1-WEEKDAY(A1, 1)+4),1,4)
            +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1, 1)+4),1,4), 1)+6)/7)

  また、後述barry houdini 氏による下記式でも同じ結果が得られます。 (2015/7/10 追加)
    =INT((A1-WEEKDAY(A1, 1)-DATE(YEAR(A1-WEEKDAY(A1, 1)+4),1,4))/7)+2
          初出:2006年5月16日 MrExcel.com / Year-Week Number

  (注) [ISO8601:週番号] と言う場合は【月曜 始まり】のみを指します
          この 『日曜 始まり』 はISO標準から外れる拡張となりますので注意して下さい。



式が長いので、VBAでユーザー定義関数にすると下記になります。

 Function ISO_WEEKNUM(ByVal argDate As Date, ByVal arg1stDayWeek As Integer) As Integer
 '[Created By Frank Kabel , Modified By K.Tsunoda]
 'http://msdn.microsoft.com/ja-jp/library/bb277364.aspx
 'http://www.h3.dion.ne.jp/~sakatsu/Excel_Tips20.htm
 '
 '[arg1stDayWeek] 1(vbSunday): Sun to Sat , 2(vbMonday): Mon to Sun

 Dim dtmYY0104 As Date
   dtmYY0104 = DateSerial(Year(argDate - Weekday(argDate, arg1stDayWeek) + 4), 1, 4)

   ISO_WEEKNUM = (argDate - dtmYY0104 + Weekday(dtmYY0104, arg1stDayWeek) + 6) \ 7
 End Function
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 日曜始まり :   =ISO_WEEKNUM( A1, 1 )
 月曜始まり :   =ISO_WEEKNUM( A1, 2 )



[ この場所へのリンク ]

---- Frank Kabel 氏による式の解説 ----

最後に、Frank Kabel氏の算出式が、どういう仕組みで作られているのかを分析してみます。
ここでは、上記の[月曜始まり曜日番号]に加工した[月曜 始まり週番号] 算出式で分析します。
したがって、
    『第1木曜日が含まれる週が、その年の第1週
      もしくは、1月4日が含まれる週が、その年の第1週』
が条件になります。

  1     2     3     4     5     6     7    ← 曜日番号:WEEKDAY( ,2)
[月]  [火]  [水]  [木]  [金]  [土]  [日]
 1/1    2     3    (4)    5     6     7    ←1月の第1週
12/31 1/1     2     3    (4)    5     6    ←1月の第1週
12/30  31   1/1     2     3    (4)    5    ←1月の第1週
12/29  30    31   1/1     2     3    (4)   ←1月の第1週
12/28  29    30    31   1/1     2     3    ←前年12月の最終週(52週 or 53週)
12/27  28    29    30    31   1/1     2    ←前年12月の最終週(52週 or 53週)
12/26  27    28    29    30    31   1/1    ←前年12月の最終週(52週 or 53週)

Frank Kabel氏の式(オリジナル)
    =INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1 - 1) + 4), 1, 3)
                  + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1 - 1) + 4), 1, 3)) + 5) / 7)

Frank Kabel氏の式([月曜始まり曜日番号]に加工した式 , 前記参照
    =INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3)
            + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) + 1, 2) + 5) / 7)

先ず、【 DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) 】の部分について

α : A1 - WEEKDAY(A1, 2)                「A1 の週」の前週末日(日曜日)
βα + 4                                       「日曜日の4日後」→A1 の週の木曜日
    → γ : DATE(YEAR(β), 1, 3)        「A1 の週の木曜日が属する年」の1月3日
                                                      (上図で「12月の年」か「1月の年」か)

=INT((A1 - γ + WEEKDAY(γ + 1, 2) + 5) / 7)

δγ + 1                                       「A1 の週の木曜日が属する年」の1月4日
    → δw : WEEKDAY(δ, 2)             「A1 の週の木曜日が属する年」の1月4日の曜日

=INT((A1 - γ + δw + 5 ) / 7)
  →  =INT((A1 - (γ - δw - 5) ) / 7)
    →  =INT((A1 - (( γ + 1) - δw - 6) ) / 7)
      →  =INT((A1 - (δ - δw - 6) ) / 7)
        →  =INT((A1 - (δ - δw) + 6) / 7)

ε : (δ - δw)   「『A1 の週の木曜日が属する年』の1月4日の週」の前週末日(日曜日):通算日の基点
  →  =INT((A1 - ε + 6) / 7)

χ : A1 - ε                      「A1  までの通算日」
  →  =INT((χ + 6) / 7)     「通算日を7で割り、週番号(1〜53)へ丸める

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
式の意味合いが判りましたので、今度は逆に仕様の方から式を組み上げてみます。
  ・ A1から『[1月4日]の週の前週末日(日曜)』を引いた通算日数を7で割って週番号を求める。
  ・ [1月4日]の『年』は、A1の週の木曜日の『年』とする。

通算日の起算点: [1月4日]の週の前週末日(日曜日)
=DATE(年, 1, 4) - WEEKDAY(DATE(年, 1, 4), 2)

A1から前週末日を引いて通算日数を求める
=A1 - (DATE(年, 1, 4) - WEEKDAY(DATE(年, 1, 4), 2))
  →  =A1 - DATE(年, 1, 4) + WEEKDAY(DATE(年, 1, 4), 2)

通算日数を7で割って週番号を求める
=INT( (A1 - DATE(年, 1, 4) + WEEKDAY(DATE(年, 1, 4), 2) + 6) / 7) ・・・ [1]式

[] については以下の式で求まります。
A1の週の木曜日→A1の週の前週末日(日曜日)+4
=(A1 - WEEKDAY(A1, 2)) + 4

[1月4日]の『年』は、A1の週の木曜日の『年』
: =YEAR(A1 - WEEKDAY(A1, 2) + 4)

[1]式に の式を組み込むと下記の式になります。
 [ISO8601 週番号] 算出式(月曜 始まり)
    =INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
          + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) + 6) / 7)

  補 : [日曜 始まり]の週番号は、曜日番号を[日曜 始まり]に変えます
    =INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 1) + 4), 1, 4)
          + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 1) + 4), 1, 4), 1) + 6) / 7)
 

Frank Kabel 氏の式(月曜始まり曜日番号に加工したもの)と比較してみると少し違います。
  =INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3)
          + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) + 1, 2) + 5) / 7)

以下のように加工してみると同じであると判ります。
=INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3)
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) + 1, 2) + 5) / 7)
    ↓
=INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3)
        + WEEKDAY((DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) + 1), 2) + 5) / 7)
    ↓
=INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3)
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) + 5) / 7)
    ↓
=INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) - 1
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) + 5 + 1) / 7)
    ↓
=INT((A1 - (DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 3) + 1)
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) + 6) / 7)
    ↓
=INT((A1 - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) + 6) / 7)

Frank Kabel 氏は、元々[日曜始まり]の曜日番号を使って[月曜始まり]の週番号を求める式を組み
上げていますので、この「日曜と月曜のズレ」から来る結果と、式の整理の過程で
    ・ 1月4日ではなく、1月3日 という日付
    ・ 通算日を週番号へ丸める際の調整値が 5 という半端な数値
が残ったのでしょう。

私がここで整理した式は、最初から[月曜始まり]の曜日番号を使って[月曜始まり]の週番号を求める
式を組み立てたおかげで
    ・ 仕様の文言に即した「1月4日」という日付を使っている
    ・ 通算日を週番号へ丸める際の調整値には 6 を使っている
となっており、式の意味・結果は同じですが、Frank Kabel 氏の式よりは幾分判り易くなったと思います。


[ この場所へのリンク ]
 ---- JavaScript code ( Frank Kabel )----

 function ISO8601WeekNumber( ArgDate ) {

   // ISO8601 week number formula (Excel) developed by Frank Kabel (Modified version)
   // =INT((A1-DATE(YEAR(A1-WEEKDAY(A1,2)+4),1,4)
   //             +WEEKDAY(DATE(YEAR(A1-WEEKDAY(A1,2)+4),1,4),2)+6)/7)
   //
   // Explanation of how the formula works.
   // (Jpn) http://addinbox.sakura.ne.jp/Excel_Tips20.htm#Frank
   // (Eng) http://addinbox.sakura.ne.jp/Excel_Tips20E.htm#Frank

   var Week = (ArgDate.getDay() || 7);    // Mon(1),Tue(2) --- Sat(6),Sun(7)

   var Date1 = new Date(ArgDate.getTime());
   Date1.setDate(Date1.getDate() - Week + 4);

   var Date2 = new Date(Date1.getFullYear(), 0, 4);    // Jan. 4
   var Date2Week = (Date2.getDay() || 7);    // Mon(1),Tue(2) --- Sat(6),Sun(7)

   var DateDiff = ((ArgDate - Date2) / 86400000) + Date2Week;

   return Math.floor((DateDiff + 6) / 7);
 }



  ---- 年を4桁で入力してボタンをクリック ----
     



[ この場所へのリンク ]

---- barry houdini 氏による式の解説 ----    (2015/7/10 追記)
    ( 初出 : 2006年5月16日  MrExcel.com / Year-Week Number )

=INT((A1 - WEEKDAY(A1, 2) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)) / 7) + 2

  1     2     3     4     5     6     7    ← 曜日番号:WEEKDAY( ,2)
[月]  [火]  [水]  [木]  [金]  [土]  [日]
 1/1    2     3    (4)    5     6     7    ←1月の第1週
12/31 1/1     2     3    (4)    5     6    ←1月の第1週
12/30  31   1/1     2     3    (4)    5    ←1月の第1週
12/29  30    31   1/1     2     3    (4)   ←1月の第1週
12/28  29    30    31   1/1     2     3    ←前年12月の最終週(52週 or 53週)
12/27  28    29    30    31   1/1     2    ←前年12月の最終週(52週 or 53週)
12/26  27    28    29    30    31   1/1    ←前年12月の最終週(52週 or 53週)

(a) 対象日付 : A1

(b) 対象日の前週末日 (日曜日)
      A1 - WEEKDAY(A1, 2)

(c) 対象日の週の木曜日
      A1 - WEEKDAY(A1, 2) + 4

(d) 「対象日の週の木曜日」が属する年
      YEAR(A1 - WEEKDAY(A1, 2) + 4)

(e) 対象日の週の週末日 (日曜日)
      A1 - WEEKDAY(A1, 2) + 7

(f) 「対象日の週の木曜日」が属する年の「1月4日」
      DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)

(g) 「対象日の週の木曜日」が属する年の「1月4日」の前週末日 (日曜日)
      DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
          - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2)

(h) この式は [ (e) - (g) ] から構築されています。
    『日曜日〜日曜日』なので、その結果(日数)は7の倍数になります。
    それを7で割った値(つまり、週番号)は 1, 2, 3 ……(整数(小数部なし))

(i) [ (e) - (g) ] の式は下記になります。
      (A1 - WEEKDAY(A1, 2) + 7)
          - ( DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
                  - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) )
 
(j) A1 - WEEKDAY(A1, 2)
        + 7
        - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
        + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2)
 
(k) -- 日数を7で割り週番号にします。また『+7』を括弧の外へ出します。 --
    ( A1 - WEEKDAY(A1, 2)
          - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)
          + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2)
    ) / 7 + 1
 
(l) ( A1 - WEEKDAY(A1, 2) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4) ) / 7
          + ( WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7 + 1
 
(m) "(A1 - WEEKDAY(A1, 2) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4))" を α で置換します。

    / 7) + (WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7 + 1
 
(n) (α / 7) を「整数部」と「小数部」に分割してみます。
    INT( α / 7) + Mod( α , 7) / 7
        + (WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7 + 1
 
(o) INT( α / 7)
        + ( Mod( α ,7) + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7
            + 1

(p) 上式の結果は (h) で示したように整数(小数部なし)になります。
      つまり、2行目の部分の計算結果も整数(小数部なし)です。
      実際に、2行目の括弧内の式を計算してみると常に 7 になります。
      つまり、2行目の部分は常に 1 になります。 -- 下記 (q) & (r) で検証してみます --

(q) Mod( α ,7) は下式です。
      Mod( (A1 - WEEKDAY(A1, 2)) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4) , 7)

      この式の意味は …… Mod( "ある日曜日" - "ある年の1月4日" , 7)

      1     2     3     4     5     6     7    ← 曜日番号:WEEKDAY( ,2)
    [月]  [火]  [水]  [木]  [金]  [土]  [日]


      (ある日曜日 - 月曜日(ある年の1月4日)= "7x + 6" 日間
      (      〃       - 火曜日(         〃          )= "7x + 5"
      (      〃       - 水曜日(         〃          )= "7x + 4"
      (      〃       - 木曜日(         〃          )= "7x + 3"
      (      〃       - 金曜日(         〃          )= "7x + 2"
      (      〃       - 土曜日(         〃          )= "7x + 1"
      (      〃       - 日曜日(         〃          )= "7x + 0"

      "6 〜 0" の部分は ( 7 - WEEKDAY("ある年の1月4日" , 2) ) で表現できます。
             ( 7 - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) )

      つまり ……
        Mod( α , 7 )
             Mod( (A1 - WEEKDAY(A1, 2)) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4) , 7 )
               Mod( ( 7x + (7 - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2)) ), 7 )
                   0 + (7 - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2))
                       7 - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2)

(r) つまり、式(o) の2行目は ……
    ( Mod( α ,7) + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7
         ( (7 - WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2))
                    + WEEKDAY(DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4), 2) ) / 7
             ( 7 ) / 7
                 1

(s) 式 (o) : INT( α / 7) + (7 / 7) + 1
          INT((A1 - WEEKDAY(A1, 2) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)) / 7) + 1 + 1

              INT((A1 - WEEKDAY(A1, 2) - DATE(YEAR(A1 - WEEKDAY(A1, 2) + 4), 1, 4)) / 7) + 2


[ この場所へのリンク ]
 ---- JavaScript code ( Barry Houdini )----

 function ISO8601WeekNumber( ArgDate ) {
   // ISO8601 week number formula (Excel) developed by Barry Houdini
   // =INT((A1-WEEKDAY(A1,2)-DATE(YEAR(A1-WEEKDAY(A1,2)+4),1,4))/7)+2
   //
   // Explanation of how the formula works.
   // (Jpn) http://addinbox.sakura.ne.jp/Excel_Tips20.htm#barry
   // (Eng) http://addinbox.sakura.ne.jp/Excel_Tips20E.htm#barry

   var Week = (ArgDate.getDay() || 7);    // Mon(1),Tue(2) --- Sat(6),Sun(7)

   var Date1 = new Date(ArgDate.getTime());
   var Date2 = new Date(ArgDate.getTime());

   Date1.setDate(Date1.getDate() - Week);
   Date2.setDate(Date2.getDate() - Week + 4);

   var Date3 = new Date(Date2.getFullYear(), 0, 4); // Jan. 4

   var DateDiff = (Date1 - Date3) / 86400000;

   return Math.floor(DateDiff / 7) + 2;
 }



  ---- 年を4桁で入力してボタンをクリック ----
     




[ この場所へのリンク ]

---- OpenOffice.org Calc でのサポート状況 ----

      ・ WEEKNUM 関数
             [ISO8601:週番号] に完全準拠した週番号が得られます。
             (月曜始まり/日曜始まり の2形式で計算できます)

      ・ WEEKNUM_ADD 関数
             Excel の WEEKNUM 関数と同じ計算を行ないます。

      ・ OOo.Basic の DatePart 関数
             [ISO8601:週番号] に完全準拠した週番号が得られます。
             (月曜始まり/日曜始まり の2形式で計算できます)

      ・ OOo.Basic の Format 関数
             "ww"(週番号)の編集文字がヘルプ未記載ですが隠しで機能しています。
             しかし、開始曜日/第1週定義 を指定する引数がありません。計算結果は
             VBA での [ Format(日付, "ww", vbSunday, vbFirstJan1) ] と同じです。


 Home   Back Page   Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2010 Allrights Reserved.