Hiroaki Nakamura - JapaneseHolidays-1.0.3

Documentation | Source

NAME

JapanseHolidays - Japanese holidays calculation library

SYNOPSIS

  isH = JapaneseHolidays.isHoliday(new Date(2007, 9 - 1, 23));
  name = JapaneseHolidays.getHolidayName(new Date(2007, 9 - 1, 23));

DESCRIPTION

This is a library for testing if a date is a Japanese holiday (precisely, "Shukujitsu" or "Furikae Kyuujitsu") or not. Also you can get the holiday name written in Japanese.

FUNCTIONS

isHoliday

Tests a specified date is a Japanese holiday or not.

  isH = JapaneseHolidays.isHoliday(new Date(2007, 9 - 1, 23)); // is true
  isH = JapaneseHolidays.isHoliday(new Date(2007, 4 - 1, 29)); // is true
  isH = JapaneseHolidays.isHoliday(new Date(2007, 4 - 1, 30)); // is true because this date is a "furikae kyuujitsu".
  isH = JapaneseHolidays.isHoliday(new Date(2007, 4 - 1, 30), false); // is false with passing includesFurikaeKyujitsu to false.

getHolidayName

Returns the holiday name (written in Japanese) for a date if the date is a holiday, or returns the empty string if the date is not a holiday.

  name = JapaneseHolidays.getHolidayName(new Date(2007, 9 - 1, 23)); // is '秋分の日' (<- a holiday name written in Japanese)
  name = JapaneseHolidays.getHolidayName(new Date(2007, 4 - 1, 29)); // is '昭和の日'
  name = JapaneseHolidays.getHolidayName(new Date(2007, 4 - 1, 30)); // is '振替休日'
  name = JapaneseHolidays.getHolidayName(new Date(2007, 4 - 1, 30), false); // is '' with passing includesFurikaeKyujitsu to false.

getHolidayAndNames

Returns an array of arrays of dates of holidays and names in a year or in a month. The first element of the nested array is a date of a holiday, and the second element is the name of that holiday.

  holidays = JapaneseHolidays.getHolidayAndNames(2007, 5 - 1); // holidays in a month
  for (i = 0; i < holidays.length; i++) {
    date = holidays[i][0];
    name = holidays[i][1];
  }

  // more examples
  holidays = JapaneseHolidays.getHolidayAndNames(2007); // holidays in a year
  holidays = JapaneseHolidays.getHolidayAndNames(2007, 9 - 1, false); // holidays excluding FurikaeKyuujitsu's.

EXAMPLES

  // usage of isHoliday() to prevent computing repeatedly holidays in a month.
  year = 2007;
  month = 5 - 1;
  holidays = JapaneseHolidays.getHolidayAndNames(year, month);
  endDate = JapaneseHolidays.getEndDateInMonth(year, month);
  for (var d = 1; d < endDate.getDate(); d++) {
    dt = new Date(year, month, d);
    isH = JapaneseHolidays.isHoliday(dt, undefined, holidays);
    name = JapaneseHolidays.getHolidayName(dt, undefined, holidays);
  }

CHANGES

ver. 1.0.3

Fixed the calculation of Shunbun days and Shuubun days. The current version passes the test for years between 1948 and 2030, and is supposed to be correct until year 2150.

ver. 1.0.2

Added dojo.provide().

ver. 1.0.1

Fixed a bug. Both isHoliday() and getHolidayName() didn't handle dates having non-zero (that is, not 00:00:00) time part.

ver. 1.0

Initial release.

AUTHOR

Hioraki Nakamura <hnakamur@gmail.com>

COPYRIGHT

This program is licensed under MIT license.

Copyright (C) 2007 Hiroaki Nakamura <hnakamur@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*
 * 日本の祝日を求めるためのモジュール
 * Ver 1.0.3: 2007-09-29
 *
 * * 1月1日 - 元日(1949年より)
 * * 1月の第2月曜日 - 成人の日(2000年より。1949~1999年は1月15日)
 * * 建国記念の日 - 政令で定める日(=2月11日)(1967年より)
 * * 春分の日 - 春分日(1949年より。21世紀前半は3月20日または21日)
 * * 4月29日 - 昭和の日(2007年より)←みどりの日(1989年~2006年、5月4日に移動)←天皇誕生日(1949年~1988年、昭和天皇存命中)
 * * 5月3日 - 憲法記念日(1949年より)
 * * 5月4日 - みどりの日(2007年より)←国民の休日(1988年~2006年)
 * * 5月5日 - こどもの日(1949年より)
 * * 7月の第3月曜日 - 海の日(2003年より。1996~2002年は7月20日)
 * * 9月の第3月曜日 - 敬老の日(2003年より。1966~2002年は9月15日)
 * * 秋分の日 - 秋分日(1948年より。21世紀前半は22日または23日)
 * * 10月の第2月曜日 - 体育の日(2000年より。1966~1999年は10月10日)
 * * 11月3日 - 文化の日(1948年より)
 * * 11月23日 - 勤労感謝の日(1948年より)
 * * 12月23日 - 天皇誕生日(1989年より)
 *
 * 参考文献:Wikipedia 国民の祝日
 * http://ja.wikipedia.org/wiki/%E5%9B%BD%E6%B0%91%E3%81%AE%E7%A5%9D%E6%97%A5
 *
 * This program is licensed under MIT license.
 *
 * Copyright (C) 2007 Hiroaki Nakamura <hnakamur@gmail.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */ 

if (typeof dojo != 'undefined')
  dojo.provide('JapaneseHolidays.JapaneseHolidays');

if (typeof JapaneseHolidays == 'undefined') JapaneseHolidays = {};

JapaneseHolidays.NAME = 'JapaneseHolidays';
JapaneseHolidays.VERSION = '1.0.3';
JapaneseHolidays.EXPORT = ['isHoliday', 'getHolidayName', 'getHolidayAndNames'];
JapaneseHolidays.EXPORT_OK = [
  'getShunbunDate', 'getShuubunDate', 'compareDates', 'getNthWeekDayInMonth',
  'getDateAfterDays', 'toStringWithWeekDay', 'zeroPad', 'leftPad',
  'getShortNameOfWeekDay'
];
JapaneseHolidays.TAGS = {
  ':common' : JapaneseHolidays.EXPORT,
  ':all' : (function() {
              var a = [];
              a.push.apply(a, JapaneseHolidays.EXPORT);
              a.push.apply(a, JapaneseHolidays.EXPORT_OK);
              return a;
            })()
};

/*
 * 指定した日が日本の祝日かどうかを返す。
 *
 * @param d 指定した日
 * @param includesFurikaeKyuujitsu 振替休日を含めるかどうか(省略時はtrue)
 * @param holidays 予め求めたgetHolidayAndNamesの結果
 *                 (省略時は内部で計算する。複数回実行するときにこの引数を
 *                 指定すれば無駄な計算の繰り返しを避けられる)
 * @return 指定した日が日本の祝日かどうか
 */
JapaneseHolidays.isHoliday = function(date, includesFurikaeKyuujitsu /* = true */, holidays) {
  return this.getHolidayName(date, includesFurikaeKyuujitsu, holidays) != '';
};

/*
 * 指定した日の日本の祝日の名前を返す。
 *
 * @param d 指定した日
 * @param includesFurikaeKyuujitsu 振替休日を含めるかどうか(省略時はtrue)
 * @param holidays 予め求めたgetHolidayAndNamesの結果
 *                 (省略時は内部で計算する。複数回実行するときにこの引数を
 *                 指定すれば無駄な計算の繰り返しを避けられる)
 * @return 指定した日の日本の祝日の名前。祝日でない場合は空文字列。
 */
JapaneseHolidays.getHolidayName = function(date, includesFurikaeKyuujitsu /* = true */,
                          holidays) {
  if (includesFurikaeKyuujitsu === undefined) includesFurikaeKyuujitsu = true;
  if (holidays === undefined) {
    holidays = this.getHolidayAndNames(
        date.getFullYear(), date.getMonth(), includesFurikaeKyuujitsu);
  }
  var d2 = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  for (var i = 0; i < holidays.length; i++) {
    if (this.compareDates(d2, holidays[i][0]) == 0) {
      return holidays[i][1];
    }
  }
  return '';
};

/*
 * 指定した年または月の日本の祝日と名前の配列を返す。
 *
 * @param year 年
 * @param month 月(省略時または-1を指定した場合は年全体の祝日を求める)
 * @param includesFurikaeKyuujitsu 振替休日を含めるかどうか(省略時はtrue)
 * @return 指定した年または月の日本の祝日と名前の配列。
 *         (例:[[new Date(2007, 9 - 1, 17), '敬老の日'],
 *               [new Date(2007, 9 - 1, 23), '秋分の日'],
 *               [new Date(2007, 9 - 1, 24), '振替休日']]
 */
JapaneseHolidays.getHolidayAndNames = function(year, month /* = -1 */,
                              includesFurikaeKyuujitsu /* = true */) {
  if (month === undefined) month = -1;
  if (includesFurikaeKyuujitsu === undefined) includesFurikaeKyuujitsu = true;

  var d;
  var holidays = [];

  // 1月
  if (month == 1 - 1 || month == -1) {
    // * 1月1日 - 元日(1949年より)
    if (year >= 1949) {
      holidays.push([new Date(year, 1 - 1, 1), '元日']);
    }

    // * 1月の第2月曜日 - 成人の日(2000年より。1949~1999年は1月15日)
    if (year >= 1949) {
      if (year >= 2000) {
        d = this.getNthWeekDayInMonth(year, 1 - 1, 2, 1);
      } else {
        d = new Date(year, 1 - 1, 15);
      }
      holidays.push([d, '成人の日']);
    }
  }

  // 2月
  if (month == 2 - 1 || month == -1) {
    // * 建国記念の日 - 政令で定める日(=2月11日)(1967年より)
    if (year >= 1967) {
      holidays.push([new Date(year, 2 - 1, 11), '建国記念の日']);
    }
  }

  // 3月
  if (month == 3 - 1 || month == -1) {
    // * 春分の日 - 春分日(1949年より。21世紀前半は3月20日または21日)
    if (year >= 1949) {
      holidays.push([this.getShunbunDate(year), '春分の日']);
    }
  }

  // 4月
  if (month == 4 - 1 || month == -1) {
    // * 4月29日 - 昭和の日(2007年より)←みどりの日(1989年~2006年、5月4日に移動)←天皇誕生日(1949年~1988年、昭和天皇存命中)
    if (year >= 1949) {
      d = new Date(year, 4 - 1, 29);
      if (year >= 2007) {
        holidays.push([d, '昭和の日']);
      } else if (year >= 1989) {
        holidays.push([d, 'みどりの日']);
      } else {
        holidays.push([d, '天皇誕生日']);
      }
    }
  }

  // 5月
  if (month == 5 - 1 || month == -1) {
    // * 5月3日 - 憲法記念日(1949年より)
    if (year >= 1949) {
      holidays.push([new Date(year, 5 - 1, 3), '憲法記念日']);
    }

    // * 5月4日 - みどりの日(2007年より)←国民の休日(1988年~2006年)
    if (year >= 1988) {
      d = new Date(year, 5 - 1, 4);
      if (year >= 2007) {
        holidays.push([d, 'みどりの日']);
      } else {
        holidays.push([d, '国民の休日']);
      }
    }

    // * 5月5日 - こどもの日(1949年より)
    if (year >= 1949) {
      holidays.push([new Date(year, 5 - 1, 5), 'こどもの日']);
    }
  }

  // 7月
  if (month == 7 - 1 || month == -1) {
    // * 7月の第3月曜日 - 海の日(2003年より。1996~2002年は7月20日)
    if (year >= 1996) {
      if (year >= 2003) {
        d = this.getNthWeekDayInMonth(year, 7 - 1, 3, 1);
      } else {
        d = new Date(year, 7 - 1, 20);
      }
      holidays.push([d, '海の日']);
    }
  }

  // 9月
  if (month == 9 - 1 || month == -1) {
    // * 9月の第3月曜日 - 敬老の日(2003年より。1966~2002年は9月15日)
    if (year >= 1966) {
      if (year >= 2003) {
        d = this.getNthWeekDayInMonth(year, 9 - 1, 3, 1);
      } else {
        d = new Date(year, 9 - 1, 15);
      }
      holidays.push([d, '敬老の日']);
    }

    // * 秋分の日 - 秋分日(1948年より。21世紀前半は22日または23日)
    if (year >= 1948) {
      holidays.push([this.getShuubunDate(year), '秋分の日']);
    }
  }

  // 10月
  if (month == 10 - 1 || month == -1) {
    // * 10月の第2月曜日 - 体育の日(2000年より。1966~1999年は10月10日)
    if (year >= 1966) {
      if (year >= 2000) {
        d = this.getNthWeekDayInMonth(year, 10 - 1, 2, 1);
      } else {
        d = new Date(year, 10 - 1, 10);
      }
      holidays.push([d, '体育の日']);
    }
  }

  // 11月
  if (month == 11 - 1 || month == -1) {
    // * 11月3日 - 文化の日(1948年より)
    if (year >= 1948) {
      holidays.push([new Date(year, 11 - 1, 3), '文化の日']);
    }
    // * 11月23日 - 勤労感謝の日(1948年より)
    if (year >= 1948) {
      holidays.push([new Date(year, 11 - 1, 23), '勤労感謝の日']);
    }
  }

  // 12月
  if (month == 12 - 1 || month == -1) {
    // * 12月23日 - 天皇誕生日(1989年より)
    if (year >= 1989) {
      holidays.push([new Date(year, 12 - 1, 23), '天皇誕生日']);
    }
  }

  return includesFurikaeKyuujitsu
    ? this.addFurikaeKyuujitsu(holidays)
    : holidays;
};

/*
 * 日本の祝日と名前を交互に含んだ配列に振替休日の要素を追加したものを返す。
 * @param holidays 日本の祝日と名前を交互に含んだ配列
 * @return 日本の祝日と名前を交互に含んだ配列に振替休日の要素を追加したもの
 *
 * 参考文献: Wikipedia 振替休日
 * http://ja.wikipedia.org/wiki/%E6%8C%AF%E6%9B%BF%E4%BC%91%E6%97%A5
 */
JapaneseHolidays.addFurikaeKyuujitsu = function(holidays) {
  var holidays2 = [];
  for (var i = 0; i < holidays.length; i++) {
    holidays2.push(holidays[i]);

    var d = holidays[i][0];
    if (d.getDay() == 0) { // Sunday
      if (this.compareDates(d, new Date(1973, 4 - 1, 29)) >= 0) {
        d = this.getDateAfterDays(d, 1);
        if (this.compareDates(d, new Date(2008, 5 - 1, 4)) >= 0) {
          while (i + 1 < holidays.length &&
              this.compareDates(d, holidays[i + 1][0]) == 0) {
            holidays2.push(holidays[++i]);
            d = this.getDateAfterDays(d, 1);
          }
          holidays2.push([d, '振替休日']);
        } else {
          if (!(i + 1 < holidays.length &&
                this.compareDates(d, holidays[i + 1][0]) == 0)) {
            holidays2.push([d, '振替休日']);
          }
        }
      }
    }
  }
  return holidays2;
};

/*
 * 指定した年の春分の日を返す。
 * @param year 年
 * @return 指定した年の春分の日
 */
JapaneseHolidays.getShunbunDate = function(year) {
  var baseDate = year <= 1999 ? 2213 : 2089;
  return new Date(year, 3 - 1,
      this.getShunbunShuubunDayHelper(year, baseDate));
};

/*
 * 指定した年の秋分の日を返す。
 * @param year 年
 * @return 指定した年の秋分の日
 */
JapaneseHolidays.getShuubunDate = function(year) {
  var baseDate = year <= 1999 ? 2525 : 2395;
  return new Date(year, 9 - 1,
      this.getShunbunShuubunDayHelper(year, baseDate));
};

/*
 * 指定した年の春分または秋分の日を天文学的に計算するためのヘルパ関数。
 * @param year 年
 * @param baseDate 計算に用いる基点の日
 * @return 指定した年の春分または秋分の月内での日
 *
 * 参考文献: 将来の春分日・秋分日の計算
 * http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/7112
 *
 * --(引用開始)-----------
 *
 * 年を y とした時、春分日(3月X日のX)、秋分日(9月X日のX)は以下
 * の式で計算できます。ただし、除算の余りは切り捨てます。
 *
 * 春分日 (31y+2213)/128-y/4+y/100    (1851年-1999年通用)
 *     (31y+2089)/128-y/4+y/100    (2000年-2150年通用)
 *
 * 秋分日 (31y+2525)/128-y/4+y/100    (1851年-1999年通用)
 *     (31y+2395)/128-y/4+y/100    (2000年-2150年通用)
 *
 * --(引用終了)-----------
 *
 * 注:上の説明では1851年以降でないと計算できないようだが、実際は1948年以降で
 *     無理矢理計算しても結果は以下のページ
 *     http://www.asahi-net.or.jp/~CI5M-NMR/misc/equinox.html
 *     で紹介されている理科年表の記録と一致した。春分の日が祝日になったのは
 *     1949年、秋分の日は1948年なので、過去についてはこの式で問題ないことにな
 *     る。2151年以降については、将来追加情報が得られたら計算式を更新すること。
 */
JapaneseHolidays.getShunbunShuubunDayHelper = function(year, baseDate) {
  return Math.floor((31 * year + baseDate) / 128) - Math.floor(year / 4) +
      Math.floor(year / 100);
};

/*
 * 2つの日時の前後関係を比較する。
 * @param d1 日時1
 * @param d2 日時2
 * @return d1のほうが前なら-1, 同じなら0, d1のほうが後なら1
 */
JapaneseHolidays.compareDates = function(d1, d2) {
  if (d1 == undefined) {
    return d2 == undefined ? 0 : -1;
  } else {
    return d2 == undefined ? 1 : d1.getTime() - d2.getTime();
  }
};

/*
 * 指定した年と月のn番目の指定した曜日の日を返す。
 * 例:2007年1月の第2月曜日
 * @param year 年
 * @param month 月(0=1月, 1=2月, ..., 11=12月)
 * @param nth n番目の指定
 * @param weekDay 曜日を表す数値
 * @return 指定した年と月のn番目の指定した曜日の日
 */
JapaneseHolidays.getNthWeekDayInMonth = function(year, month, nth, weekday) {
  var d = new Date(year, month, 1);
  while (d.getDay() != weekday) {
    d = this.getDateAfterDays(d, 1);
  }
  return this.getDateAfterDays(d, (nth - 1) * 7);
};

/*
 * 指定した日から指定した日数だけ後の日を返す。
 * @param date 日
 * @param days 日数
 * @return 指定した日から指定した日数だけ後の日。
 */
JapaneseHolidays.getDateAfterDays = function(date, days) {
  return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
};

JapaneseHolidays.toStringWithWeekDay = function(date) {
  return String(date.getFullYear()) + '/index.html' +
    this.zeroPad(String(date.getMonth() + 1), 2) + '/index.html' +
    this.zeroPad(String(date.getDate()), 2) +
    '(' + this.getShortNameOfWeekDay(date.getDay()) + ')';
};

JapaneseHolidays.zeroPad = function(text, length) {
  return this.leftPad(text, length, '0');
};

JapaneseHolidays.leftPad = function(text, length, padding) {
  while (text.length < length) {
    text = padding + text;
  }
  return text;
};

/*
 * 曜日を表す数値に対応する曜日の短い名前を返す。
 * @param weekDay 曜日を表す数値
 * @return 対応する曜日の短い名前
 */
JapaneseHolidays.getShortNameOfWeekDay = function(weekday) {
  return ['日', '月', '火', '水', '木', '金', '土'][weekday];
};

/*
 * 月末の日を返す。
 * @param year 年
 * @param month 月(0=1月, 1=2月, ..., 11=12月)
 * @return 月末の日
 */
JapaneseHolidays.getEndDateInMonth = function(year, month) {
  return this.getDateAfterDays(new Date(year, month + 1, 1), -1);
};