From f388f19d066c1d2df132a0ae12bc683e0b346363 Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Tue, 16 Mar 2021 09:58:30 +0900 Subject: [PATCH 1/9] add kr holidays except lunar dates --- v2/kr/kr_holidays.go | 111 ++++++++++++++++++++++++++++++++++++++ v2/kr/kr_holidays_test.go | 105 ++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 v2/kr/kr_holidays.go create mode 100644 v2/kr/kr_holidays_test.go diff --git a/v2/kr/kr_holidays.go b/v2/kr/kr_holidays.go new file mode 100644 index 0000000..87234b8 --- /dev/null +++ b/v2/kr/kr_holidays.go @@ -0,0 +1,111 @@ +// (c) Rick Arnold. Licensed under the BSD license (see LICENSE). + +// Package kr provides holiday definitions for the Republic of Korea. +package kr + +import ( + "time" + + "github.com/rickar/cal/v2" + "github.com/rickar/cal/v2/aa" +) + +var ( + // Standard KR weekend substitution rules: + // https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98_%EA%B3%B5%ED%9C%B4%EC%9D%BC + // If the Lunar New Year holiday and Chuseok holiday overlap with other public holidays, including Sundays, + // the first weekday after the holiday shall be an alternative holiday, and if Children's Day overlaps with other + // public holidays or Saturdays, the first weekday shall be an alternative holiday (Article 3.[1] New November 5, 2013). + + // 설날 연휴와 추석 연휴가 일요일을 포함한 다른 공휴일과 겹칠 경우에는 연휴 다음 첫번째 평일을 대체공휴일로 하고, + // 어린이날이 다른 공휴일이나 토요일과 겹칠 경우에는 그 다음 첫번째 평일을 대체공휴일로 한다. + // (관공서의 공휴일에 관한 규정 제3조.[1] 2013년 11월 5일 신설) + + // Saturdays and Sundays move to next weekday + + weekendAlt = []cal.AltDay{ + {Day: time.Saturday, Offset: 2}, + {Day: time.Sunday, Offset: 1}, + } + + // NewYear represents New Year's Day on 1-Jan + NewYear = aa.NewYear.Clone(&cal.Holiday{Name: "새해 첫날", Type: cal.ObservancePublic}) + + // TODO: 설날 LunarNewYear + // Observed: weekendAlt, + + // IndependenceMovementDay represents 3.1절 on the 1-Mar + IndependenceMovementDay = &cal.Holiday{ + Name: "3.1절", + Type: cal.ObservancePublic, + Month: time.March, + Day: 1, + Func: cal.CalcDayOfMonth, + } + + // ChildrensDay represents 어린이날 on the 5-May + ChildrensDay = &cal.Holiday{ + Name: "어린이날", + Type: cal.ObservancePublic, + Month: time.May, + Day: 5, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // TODO: 부처님 오신 날 lunar + + // MemorialDay represents 현충일 on the 6-June + MemorialDay = &cal.Holiday{ + Name: "현충일", + Type: cal.ObservancePublic, + Month: time.June, + Day: 6, + Func: cal.CalcDayOfMonth, + } + + // LiberationDay represents 광복절 on the 15-August + LiberationDay = &cal.Holiday{ + Name: "광복절", + Type: cal.ObservancePublic, + Month: time.August, + Day: 15, + Func: cal.CalcDayOfMonth, + } + + // TODO: 추석 lunar Chuseok + // Observed: weekendAlt, + + // FoundationDay represents 개천절 on the 3-October + FoundationDay = &cal.Holiday{ + Name: "개천절", + Type: cal.ObservancePublic, + Month: time.October, + Day: 3, + Func: cal.CalcDayOfMonth, + } + + // HangeulDay represents 개천절 on the 9-October + HangeulDay = &cal.Holiday{ + Name: "한글날", + Type: cal.ObservancePublic, + Month: time.October, + Day: 9, + Func: cal.CalcDayOfMonth, + } + + // ChristmasDay represents 성탄절 on the 25-Dec + ChristmasDay = aa.ChristmasDay.Clone(&cal.Holiday{Name: "성탄절", Type: cal.ObservancePublic}) + + // Holidays provides a list of the standard national holidays + Holidays = []*cal.Holiday{ + NewYear, + IndependenceMovementDay, + ChildrensDay, + MemorialDay, + LiberationDay, + FoundationDay, + HangeulDay, + ChristmasDay, + } +) diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go new file mode 100644 index 0000000..0bec92c --- /dev/null +++ b/v2/kr/kr_holidays_test.go @@ -0,0 +1,105 @@ +// (c) Rick Arnold. Licensed under the BSD license (see LICENSE). + +package kr + +import ( + "testing" + "time" + + "github.com/rickar/cal/v2" +) + +func d(y, m, d int) time.Time { + return time.Date(y, time.Month(m), d, 0, 0, 0, 0, cal.DefaultLoc) +} + +func TestHolidays(t *testing.T) { + tests := []struct { + h *cal.Holiday + y int + wantAct time.Time + wantObs time.Time + }{ + {NewYear, 2015, d(2015, 1, 1), d(2015, 1, 1)}, + {NewYear, 2016, d(2016, 1, 1), d(2016, 1, 1)}, + {NewYear, 2017, d(2017, 1, 1), d(2017, 1, 1)}, + {NewYear, 2018, d(2018, 1, 1), d(2018, 1, 1)}, + {NewYear, 2019, d(2019, 1, 1), d(2019, 1, 1)}, + {NewYear, 2020, d(2020, 1, 1), d(2020, 1, 1)}, + {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, + {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, + + {IndependenceMovementDay, 2015, d(2015, 3, 1), d(2015, 3, 1)}, + {IndependenceMovementDay, 2016, d(2016, 3, 1), d(2016, 3, 1)}, + {IndependenceMovementDay, 2017, d(2017, 3, 1), d(2017, 3, 1)}, + {IndependenceMovementDay, 2018, d(2018, 3, 1), d(2018, 3, 1)}, + {IndependenceMovementDay, 2019, d(2019, 3, 1), d(2019, 3, 1)}, + {IndependenceMovementDay, 2020, d(2020, 3, 1), d(2020, 3, 1)}, + {IndependenceMovementDay, 2021, d(2021, 3, 1), d(2021, 3, 1)}, + {IndependenceMovementDay, 2022, d(2022, 3, 1), d(2022, 3, 1)}, + + {ChildrensDay, 2015, d(2015, 5, 5), d(2015, 5, 5)}, + {ChildrensDay, 2016, d(2016, 5, 5), d(2016, 5, 5)}, + {ChildrensDay, 2017, d(2017, 5, 5), d(2017, 5, 5)}, + {ChildrensDay, 2018, d(2018, 5, 5), d(2018, 5, 7)}, + {ChildrensDay, 2019, d(2019, 5, 5), d(2019, 5, 6)}, + {ChildrensDay, 2020, d(2020, 5, 5), d(2020, 5, 5)}, + {ChildrensDay, 2021, d(2021, 5, 5), d(2021, 5, 5)}, + {ChildrensDay, 2022, d(2022, 5, 5), d(2022, 5, 5)}, + + {MemorialDay, 2015, d(2015, 6, 6), d(2015, 6, 6)}, + {MemorialDay, 2016, d(2016, 6, 6), d(2016, 6, 6)}, + {MemorialDay, 2017, d(2017, 6, 6), d(2017, 6, 6)}, + {MemorialDay, 2018, d(2018, 6, 6), d(2018, 6, 6)}, + {MemorialDay, 2019, d(2019, 6, 6), d(2019, 6, 6)}, + {MemorialDay, 2020, d(2020, 6, 6), d(2020, 6, 6)}, + {MemorialDay, 2021, d(2021, 6, 6), d(2021, 6, 6)}, + {MemorialDay, 2022, d(2022, 6, 6), d(2022, 6, 6)}, + + {LiberationDay, 2015, d(2015, 8, 15), d(2015, 8, 15)}, + {LiberationDay, 2016, d(2016, 8, 15), d(2016, 8, 15)}, + {LiberationDay, 2017, d(2017, 8, 15), d(2017, 8, 15)}, + {LiberationDay, 2018, d(2018, 8, 15), d(2018, 8, 15)}, + {LiberationDay, 2019, d(2019, 8, 15), d(2019, 8, 15)}, + {LiberationDay, 2020, d(2020, 8, 15), d(2020, 8, 15)}, + {LiberationDay, 2021, d(2021, 8, 15), d(2021, 8, 15)}, + {LiberationDay, 2022, d(2022, 8, 15), d(2022, 8, 15)}, + + {FoundationDay, 2015, d(2015, 10, 3), d(2015, 10, 3)}, + {FoundationDay, 2016, d(2016, 10, 3), d(2016, 10, 3)}, + {FoundationDay, 2017, d(2017, 10, 3), d(2017, 10, 3)}, + {FoundationDay, 2018, d(2018, 10, 3), d(2018, 10, 3)}, + {FoundationDay, 2019, d(2019, 10, 3), d(2019, 10, 3)}, + {FoundationDay, 2020, d(2020, 10, 3), d(2020, 10, 3)}, + {FoundationDay, 2021, d(2021, 10, 3), d(2021, 10, 3)}, + {FoundationDay, 2022, d(2022, 10, 3), d(2022, 10, 3)}, + + {HangeulDay, 2015, d(2015, 10, 9), d(2015, 10, 9)}, + {HangeulDay, 2016, d(2016, 10, 9), d(2016, 10, 9)}, + {HangeulDay, 2017, d(2017, 10, 9), d(2017, 10, 9)}, + {HangeulDay, 2018, d(2018, 10, 9), d(2018, 10, 9)}, + {HangeulDay, 2019, d(2019, 10, 9), d(2019, 10, 9)}, + {HangeulDay, 2020, d(2020, 10, 9), d(2020, 10, 9)}, + {HangeulDay, 2021, d(2021, 10, 9), d(2021, 10, 9)}, + {HangeulDay, 2022, d(2022, 10, 9), d(2022, 10, 9)}, + + {ChristmasDay, 2015, d(2015, 12, 25), d(2015, 12, 25)}, + {ChristmasDay, 2016, d(2016, 12, 25), d(2016, 12, 25)}, + {ChristmasDay, 2017, d(2017, 12, 25), d(2017, 12, 25)}, + {ChristmasDay, 2018, d(2018, 12, 25), d(2018, 12, 25)}, + {ChristmasDay, 2019, d(2019, 12, 25), d(2019, 12, 25)}, + {ChristmasDay, 2020, d(2020, 12, 25), d(2020, 12, 25)}, + {ChristmasDay, 2021, d(2021, 12, 25), d(2021, 12, 25)}, + {ChristmasDay, 2022, d(2022, 12, 25), d(2022, 12, 25)}, + } + + for _, test := range tests { + gotAct, gotObs := test.h.Calc(test.y) + if !gotAct.Equal(test.wantAct) { + t.Errorf("%s %d: got actual: %s, want: %s", test.h.Name, test.y, gotAct.String(), test.wantAct.String()) + } + if !gotObs.Equal(test.wantObs) { + t.Errorf("%s %d: got observed: %s, want: %s", test.h.Name, test.y, gotObs.String(), test.wantObs.String()) + } + } +} From 543e30c9958c0516630e2ac5d30c7c3d6fd87ffc Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Tue, 16 Mar 2021 17:39:51 +0900 Subject: [PATCH 2/9] i want use 4 spaces indent rather than TAB --- v2/kr/.editorconfig | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 v2/kr/.editorconfig diff --git a/v2/kr/.editorconfig b/v2/kr/.editorconfig new file mode 100644 index 0000000..a7ac603 --- /dev/null +++ b/v2/kr/.editorconfig @@ -0,0 +1,9 @@ +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 4 From 4d0f1ab31861fd1db409f6be1050e0c06bdbbd80 Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Tue, 16 Mar 2021 17:47:47 +0900 Subject: [PATCH 3/9] implement Sol2Lun(chinese solar) TODO it must be convert korean lunar calendar --- v2/kr/data.go | 36 ++++++++ v2/kr/kr_holidays_test.go | 186 +++++++++++++++++++++----------------- v2/kr/lunar.go | 136 ++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 84 deletions(-) create mode 100644 v2/kr/data.go create mode 100644 v2/kr/lunar.go diff --git a/v2/kr/data.go b/v2/kr/data.go new file mode 100644 index 0000000..d347714 --- /dev/null +++ b/v2/kr/data.go @@ -0,0 +1,36 @@ +package kr + +// LunarInfoList +// each value contains lunar year's leap month data as hexadecimal +// 0x07954(year 2020) represents as bianry `0111100101010100` +// first 12 bits includes days of each month length +// Month|01 02 03 04 05 06 07 08 09 10 11 12 +// -----|----------------------------------- +// Value| 0 1 1 1 1 0 0 1 0 1 0 1 +// if values is 1 that month has 30 days else 29 +// rest 4 bits has leap month data +// binary `0100` represents as decimal number 4 +// lunar year 2020 has leap month and 4(April) is that +var LunarInfoList = []int{ + 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909 + 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919 + 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929 + 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939 + 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949 + 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959 + 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969 + 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979 + 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989 + 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999 + 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009 + 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019 + 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029 + 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039 + 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049 + 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, //2050-2059 + 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069 + 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079 + 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089 + 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099 + 0x0d520, //2100 +} diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go index 0bec92c..0b612ca 100644 --- a/v2/kr/kr_holidays_test.go +++ b/v2/kr/kr_holidays_test.go @@ -3,103 +3,121 @@ package kr import ( - "testing" - "time" + "fmt" + "testing" + "time" - "github.com/rickar/cal/v2" + "github.com/rickar/cal/v2" ) func d(y, m, d int) time.Time { - return time.Date(y, time.Month(m), d, 0, 0, 0, 0, cal.DefaultLoc) + return time.Date(y, time.Month(m), d, 0, 0, 0, 0, cal.DefaultLoc) } func TestHolidays(t *testing.T) { - tests := []struct { - h *cal.Holiday - y int - wantAct time.Time - wantObs time.Time - }{ - {NewYear, 2015, d(2015, 1, 1), d(2015, 1, 1)}, - {NewYear, 2016, d(2016, 1, 1), d(2016, 1, 1)}, - {NewYear, 2017, d(2017, 1, 1), d(2017, 1, 1)}, - {NewYear, 2018, d(2018, 1, 1), d(2018, 1, 1)}, - {NewYear, 2019, d(2019, 1, 1), d(2019, 1, 1)}, - {NewYear, 2020, d(2020, 1, 1), d(2020, 1, 1)}, - {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, - {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, + tests := []struct { + h *cal.Holiday + y int + wantAct time.Time + wantObs time.Time + }{ + {NewYear, 2015, d(2015, 1, 1), d(2015, 1, 1)}, + {NewYear, 2016, d(2016, 1, 1), d(2016, 1, 1)}, + {NewYear, 2017, d(2017, 1, 1), d(2017, 1, 1)}, + {NewYear, 2018, d(2018, 1, 1), d(2018, 1, 1)}, + {NewYear, 2019, d(2019, 1, 1), d(2019, 1, 1)}, + {NewYear, 2020, d(2020, 1, 1), d(2020, 1, 1)}, + {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, + {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, - {IndependenceMovementDay, 2015, d(2015, 3, 1), d(2015, 3, 1)}, - {IndependenceMovementDay, 2016, d(2016, 3, 1), d(2016, 3, 1)}, - {IndependenceMovementDay, 2017, d(2017, 3, 1), d(2017, 3, 1)}, - {IndependenceMovementDay, 2018, d(2018, 3, 1), d(2018, 3, 1)}, - {IndependenceMovementDay, 2019, d(2019, 3, 1), d(2019, 3, 1)}, - {IndependenceMovementDay, 2020, d(2020, 3, 1), d(2020, 3, 1)}, - {IndependenceMovementDay, 2021, d(2021, 3, 1), d(2021, 3, 1)}, - {IndependenceMovementDay, 2022, d(2022, 3, 1), d(2022, 3, 1)}, + {IndependenceMovementDay, 2015, d(2015, 3, 1), d(2015, 3, 1)}, + {IndependenceMovementDay, 2016, d(2016, 3, 1), d(2016, 3, 1)}, + {IndependenceMovementDay, 2017, d(2017, 3, 1), d(2017, 3, 1)}, + {IndependenceMovementDay, 2018, d(2018, 3, 1), d(2018, 3, 1)}, + {IndependenceMovementDay, 2019, d(2019, 3, 1), d(2019, 3, 1)}, + {IndependenceMovementDay, 2020, d(2020, 3, 1), d(2020, 3, 1)}, + {IndependenceMovementDay, 2021, d(2021, 3, 1), d(2021, 3, 1)}, + {IndependenceMovementDay, 2022, d(2022, 3, 1), d(2022, 3, 1)}, - {ChildrensDay, 2015, d(2015, 5, 5), d(2015, 5, 5)}, - {ChildrensDay, 2016, d(2016, 5, 5), d(2016, 5, 5)}, - {ChildrensDay, 2017, d(2017, 5, 5), d(2017, 5, 5)}, - {ChildrensDay, 2018, d(2018, 5, 5), d(2018, 5, 7)}, - {ChildrensDay, 2019, d(2019, 5, 5), d(2019, 5, 6)}, - {ChildrensDay, 2020, d(2020, 5, 5), d(2020, 5, 5)}, - {ChildrensDay, 2021, d(2021, 5, 5), d(2021, 5, 5)}, - {ChildrensDay, 2022, d(2022, 5, 5), d(2022, 5, 5)}, + {ChildrensDay, 2015, d(2015, 5, 5), d(2015, 5, 5)}, + {ChildrensDay, 2016, d(2016, 5, 5), d(2016, 5, 5)}, + {ChildrensDay, 2017, d(2017, 5, 5), d(2017, 5, 5)}, + {ChildrensDay, 2018, d(2018, 5, 5), d(2018, 5, 7)}, + {ChildrensDay, 2019, d(2019, 5, 5), d(2019, 5, 6)}, + {ChildrensDay, 2020, d(2020, 5, 5), d(2020, 5, 5)}, + {ChildrensDay, 2021, d(2021, 5, 5), d(2021, 5, 5)}, + {ChildrensDay, 2022, d(2022, 5, 5), d(2022, 5, 5)}, - {MemorialDay, 2015, d(2015, 6, 6), d(2015, 6, 6)}, - {MemorialDay, 2016, d(2016, 6, 6), d(2016, 6, 6)}, - {MemorialDay, 2017, d(2017, 6, 6), d(2017, 6, 6)}, - {MemorialDay, 2018, d(2018, 6, 6), d(2018, 6, 6)}, - {MemorialDay, 2019, d(2019, 6, 6), d(2019, 6, 6)}, - {MemorialDay, 2020, d(2020, 6, 6), d(2020, 6, 6)}, - {MemorialDay, 2021, d(2021, 6, 6), d(2021, 6, 6)}, - {MemorialDay, 2022, d(2022, 6, 6), d(2022, 6, 6)}, + {MemorialDay, 2015, d(2015, 6, 6), d(2015, 6, 6)}, + {MemorialDay, 2016, d(2016, 6, 6), d(2016, 6, 6)}, + {MemorialDay, 2017, d(2017, 6, 6), d(2017, 6, 6)}, + {MemorialDay, 2018, d(2018, 6, 6), d(2018, 6, 6)}, + {MemorialDay, 2019, d(2019, 6, 6), d(2019, 6, 6)}, + {MemorialDay, 2020, d(2020, 6, 6), d(2020, 6, 6)}, + {MemorialDay, 2021, d(2021, 6, 6), d(2021, 6, 6)}, + {MemorialDay, 2022, d(2022, 6, 6), d(2022, 6, 6)}, - {LiberationDay, 2015, d(2015, 8, 15), d(2015, 8, 15)}, - {LiberationDay, 2016, d(2016, 8, 15), d(2016, 8, 15)}, - {LiberationDay, 2017, d(2017, 8, 15), d(2017, 8, 15)}, - {LiberationDay, 2018, d(2018, 8, 15), d(2018, 8, 15)}, - {LiberationDay, 2019, d(2019, 8, 15), d(2019, 8, 15)}, - {LiberationDay, 2020, d(2020, 8, 15), d(2020, 8, 15)}, - {LiberationDay, 2021, d(2021, 8, 15), d(2021, 8, 15)}, - {LiberationDay, 2022, d(2022, 8, 15), d(2022, 8, 15)}, + {LiberationDay, 2015, d(2015, 8, 15), d(2015, 8, 15)}, + {LiberationDay, 2016, d(2016, 8, 15), d(2016, 8, 15)}, + {LiberationDay, 2017, d(2017, 8, 15), d(2017, 8, 15)}, + {LiberationDay, 2018, d(2018, 8, 15), d(2018, 8, 15)}, + {LiberationDay, 2019, d(2019, 8, 15), d(2019, 8, 15)}, + {LiberationDay, 2020, d(2020, 8, 15), d(2020, 8, 15)}, + {LiberationDay, 2021, d(2021, 8, 15), d(2021, 8, 15)}, + {LiberationDay, 2022, d(2022, 8, 15), d(2022, 8, 15)}, - {FoundationDay, 2015, d(2015, 10, 3), d(2015, 10, 3)}, - {FoundationDay, 2016, d(2016, 10, 3), d(2016, 10, 3)}, - {FoundationDay, 2017, d(2017, 10, 3), d(2017, 10, 3)}, - {FoundationDay, 2018, d(2018, 10, 3), d(2018, 10, 3)}, - {FoundationDay, 2019, d(2019, 10, 3), d(2019, 10, 3)}, - {FoundationDay, 2020, d(2020, 10, 3), d(2020, 10, 3)}, - {FoundationDay, 2021, d(2021, 10, 3), d(2021, 10, 3)}, - {FoundationDay, 2022, d(2022, 10, 3), d(2022, 10, 3)}, + {FoundationDay, 2015, d(2015, 10, 3), d(2015, 10, 3)}, + {FoundationDay, 2016, d(2016, 10, 3), d(2016, 10, 3)}, + {FoundationDay, 2017, d(2017, 10, 3), d(2017, 10, 3)}, + {FoundationDay, 2018, d(2018, 10, 3), d(2018, 10, 3)}, + {FoundationDay, 2019, d(2019, 10, 3), d(2019, 10, 3)}, + {FoundationDay, 2020, d(2020, 10, 3), d(2020, 10, 3)}, + {FoundationDay, 2021, d(2021, 10, 3), d(2021, 10, 3)}, + {FoundationDay, 2022, d(2022, 10, 3), d(2022, 10, 3)}, - {HangeulDay, 2015, d(2015, 10, 9), d(2015, 10, 9)}, - {HangeulDay, 2016, d(2016, 10, 9), d(2016, 10, 9)}, - {HangeulDay, 2017, d(2017, 10, 9), d(2017, 10, 9)}, - {HangeulDay, 2018, d(2018, 10, 9), d(2018, 10, 9)}, - {HangeulDay, 2019, d(2019, 10, 9), d(2019, 10, 9)}, - {HangeulDay, 2020, d(2020, 10, 9), d(2020, 10, 9)}, - {HangeulDay, 2021, d(2021, 10, 9), d(2021, 10, 9)}, - {HangeulDay, 2022, d(2022, 10, 9), d(2022, 10, 9)}, + {HangeulDay, 2015, d(2015, 10, 9), d(2015, 10, 9)}, + {HangeulDay, 2016, d(2016, 10, 9), d(2016, 10, 9)}, + {HangeulDay, 2017, d(2017, 10, 9), d(2017, 10, 9)}, + {HangeulDay, 2018, d(2018, 10, 9), d(2018, 10, 9)}, + {HangeulDay, 2019, d(2019, 10, 9), d(2019, 10, 9)}, + {HangeulDay, 2020, d(2020, 10, 9), d(2020, 10, 9)}, + {HangeulDay, 2021, d(2021, 10, 9), d(2021, 10, 9)}, + {HangeulDay, 2022, d(2022, 10, 9), d(2022, 10, 9)}, - {ChristmasDay, 2015, d(2015, 12, 25), d(2015, 12, 25)}, - {ChristmasDay, 2016, d(2016, 12, 25), d(2016, 12, 25)}, - {ChristmasDay, 2017, d(2017, 12, 25), d(2017, 12, 25)}, - {ChristmasDay, 2018, d(2018, 12, 25), d(2018, 12, 25)}, - {ChristmasDay, 2019, d(2019, 12, 25), d(2019, 12, 25)}, - {ChristmasDay, 2020, d(2020, 12, 25), d(2020, 12, 25)}, - {ChristmasDay, 2021, d(2021, 12, 25), d(2021, 12, 25)}, - {ChristmasDay, 2022, d(2022, 12, 25), d(2022, 12, 25)}, - } + {ChristmasDay, 2015, d(2015, 12, 25), d(2015, 12, 25)}, + {ChristmasDay, 2016, d(2016, 12, 25), d(2016, 12, 25)}, + {ChristmasDay, 2017, d(2017, 12, 25), d(2017, 12, 25)}, + {ChristmasDay, 2018, d(2018, 12, 25), d(2018, 12, 25)}, + {ChristmasDay, 2019, d(2019, 12, 25), d(2019, 12, 25)}, + {ChristmasDay, 2020, d(2020, 12, 25), d(2020, 12, 25)}, + {ChristmasDay, 2021, d(2021, 12, 25), d(2021, 12, 25)}, + {ChristmasDay, 2022, d(2022, 12, 25), d(2022, 12, 25)}, + } - for _, test := range tests { - gotAct, gotObs := test.h.Calc(test.y) - if !gotAct.Equal(test.wantAct) { - t.Errorf("%s %d: got actual: %s, want: %s", test.h.Name, test.y, gotAct.String(), test.wantAct.String()) - } - if !gotObs.Equal(test.wantObs) { - t.Errorf("%s %d: got observed: %s, want: %s", test.h.Name, test.y, gotObs.String(), test.wantObs.String()) - } - } + for _, test := range tests { + gotAct, gotObs := test.h.Calc(test.y) + if !gotAct.Equal(test.wantAct) { + t.Errorf("%s %d: got actual: %s, want: %s", test.h.Name, test.y, gotAct.String(), test.wantAct.String()) + } + if !gotObs.Equal(test.wantObs) { + t.Errorf("%s %d: got observed: %s, want: %s", test.h.Name, test.y, gotObs.String(), test.wantObs.String()) + } + } +} + +func Example_lunar() { + // http://tool-box.info/blog/archives/1504-Korean-Chinese-Lunar-Calendar-Difference.html + // gregorian: 2020-02-23 ~ 2020-03-23 + // korean lunar: 2020-01-30 ~ 2020-02-29 + // chinese lunar: 2020-02-01 ~ 2020-02-30 + fmt.Println(Sol2Lun(d(2020, 2, 22))) + fmt.Println(Sol2Lun(d(2020, 2, 23))) + fmt.Println(Sol2Lun(d(2020, 3, 2))) + fmt.Println(Sol2Lun(d(2020, 5, 5))) // leap month + + // Output: + // [2020 1 29] false + // [2020 1 30] false + // [2020 2 8] false + // [2020 4 13] true } diff --git a/v2/kr/lunar.go b/v2/kr/lunar.go new file mode 100644 index 0000000..269f3c0 --- /dev/null +++ b/v2/kr/lunar.go @@ -0,0 +1,136 @@ +package kr + +// Get source from https://github.com/godcong/chronos and rewrite. +// cause upon package does not export functions. + +import ( + "time" +) + +const ( + MINDATE = -2206513672 // 1900-01-30 unix timestamp + MAXDATE = 4102326000 // 2099-12-31 unix timestamp + + MINYEAR = 1900 + MAXYEAR = 2100 +) + +// Lun2Sol converts to solar calendar time +// TODO: implement if needed +// func Lun2Sol(year, month, day int) time.Time { +// return time.Now() +// } + +// Sol2Lun converts to lunar year/month/day and if it is belongs to the leap month +func Sol2Lun(t time.Time) (ymd [3]int, isLeap bool) { + offset := offsetDays(MINDATE, t) + year, offset := lunarYearByOffset(offset) + leapMonth := leapMonth(year) + tmp := leapMonth > 0 + + var month, days int + for month = 1; month <= 12; month++ { + if month == leapMonth+1 && tmp { + days = lengthOfLeapMonth(year) + tmp = false + month-- + } else { + days = lengthOfMonth(year, month) + } + + if offset-days <= 0 { + break + } + + offset -= days + } + + ymd[0], ymd[1], ymd[2] = year, month, offset + return ymd, month == leapMonth +} + +// offsetDays count offsets(days) between two timestamps +func offsetDays(timestamp int64, targetDate time.Time) int { + return int(float64(targetDate.Unix()-timestamp)/86400.0 + 0.5) +} + +// lunarYearByOffset calculate lunar year since MINYEAR by offset days +func lunarYearByOffset(offset int) (int, int) { + var year int + for year = MINYEAR; year <= MAXYEAR; year++ { + days := lengthOfYear(year) + if offset-days < 1 { + break + } + offset -= days + } + + return year, offset +} + +// lengthOfYear length of days of year +func lengthOfYear(year int) int { + length := 348 + info := getLunarInfo(year) + + // 1000000000000000 to 10000 + for mask := 0x8000; mask > 0x8; mask >>= 1 { + if info&mask != 0 { + length++ + } + } + + return length + lengthOfLeapMonth(year) +} + +// lengthOfMonth length of days of year/month +func lengthOfMonth(year, month int) int { + if month < 1 || month > 12 { + return -1 + } + + info := getLunarInfo(year) + if info&(0x10000>>uint32(month)) != 0 { + return 30 + } + + return 29 +} + +// lengthOfLeapMonth length of days of year/month if it is leap month +func lengthOfLeapMonth(year int) int { + if !hasLeapMonth(year) { + return 0 + } + + info := getLunarInfo(year) + if info&0x10000 != 0 { + return 30 + } + return 29 +} + +// leapMonth returns leap month if leap year +func leapMonth(year int) int { + info := getLunarInfo(year) + return info & 0xf +} + +// hasLeapMonth `year` has leap month or not +func hasLeapMonth(year int) bool { + return leapMonth(year) != 0 +} + +// isLeapMonth is leap month or not +func isLeapMonth(year, month int) bool { + return leapMonth(year) == month +} + +// getLunarInfo get pre-calcuated data by lunar year +func getLunarInfo(year int) int { + idx := year - MINYEAR + if idx < 0 || idx > len(LunarInfoList) { + return 0 + } + return LunarInfoList[idx] +} From 904123c02b7831d55c49dcde085cd777090980ed Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Tue, 16 Mar 2021 23:57:57 +0900 Subject: [PATCH 4/9] add kr.Solar2Lunar converts to Korean lunar calendar --- v2/kr/data.go | 1196 +++++++++++++++++++++++++++++++++++++ v2/kr/kr_holidays_test.go | 17 +- v2/kr/lunar.go | 58 ++ 3 files changed, 1266 insertions(+), 5 deletions(-) diff --git a/v2/kr/data.go b/v2/kr/data.go index d347714..442a58c 100644 --- a/v2/kr/data.go +++ b/v2/kr/data.go @@ -34,3 +34,1199 @@ var LunarInfoList = []int{ 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099 0x0d520, //2100 } + +var MonthTable = []int{ + 0, 29, 59, 89, 118, 147, 177, 206, + 236, 265, 294, 324, 354, 383, 413, 443, + 472, 502, 531, 561, 590, 620, 649, 678, + 708, 738, 767, 797, 826, 856, 886, 915, + 945, 974, 1004, 1033, 1063, 1092, 1122, 1151, + 1181, 1210, 1240, 1269, 1299, 1329, 1358, 1388, + 1417, 1447, 1476, 1505, 1535, 1564, 1594, 1623, + 1653, 1683, 1713, 1742, 1772, 1801, 1831, 1860, + 1889, 1919, 1948, 1978, 2007, 2037, 2067, 2096, + 2126, 2156, 2185, 2215, 2245, 2274, 2303, 2332, + 2361, 2391, 2421, 2450, 2480, 2510, 2540, 2569, + 2599, 2628, 2658, 2687, 2716, 2745, 2775, 2804, + 2834, 2864, 2894, 2923, 2953, 2983, 3012, 3041, + 3071, 3100, 3129, 3159, 3188, 3218, 3248, 3277, + 3307, 3337, 3367, 3396, 3425, 3455, 3484, 3513, + 3543, 3572, 3602, 3632, 3661, 3691, 3721, 3750, + 3780, 3809, 3839, 3868, 3898, 3927, 3956, 3986, + 4015, 4045, 4075, 4104, 4134, 4164, 4193, 4223, + 4252, 4282, 4311, 4341, 4370, 4399, 4429, 4458, + 4488, 4518, 4547, 4577, 4607, 4636, 4666, 4695, + 4725, 4754, 4783, 4813, 4842, 4872, 4901, 4931, + 4961, 4990, 5020, 5050, 5079, 5109, 5138, 5167, + 5197, 5226, 5256, 5285, 5315, 5344, 5374, 5404, + 5434, 5463, 5493, 5522, 5552, 5581, 5610, 5639, + 5669, 5698, 5728, 5758, 5788, 5817, 5847, 5877, + 5906, 5936, 5965, 5994, 6023, 6053, 6082, 6112, + 6142, 6171, 6201, 6231, 6261, 6290, 6320, 6349, + 6378, 6407, 6437, 6466, 6496, 6525, 6555, 6585, + 6615, 6644, 6674, 6703, 6733, 6762, 6791, 6821, + 6850, 6880, 6909, 6939, 6969, 6998, 7028, 7058, + 7087, 7117, 7146, 7176, 7205, 7234, 7264, 7293, + 7323, 7352, 7382, 7412, 7441, 7471, 7501, 7530, + 7560, 7589, 7618, 7648, 7677, 7707, 7736, 7766, + 7795, 7825, 7855, 7884, 7914, 7944, 7973, 8003, + 8032, 8061, 8091, 8120, 8150, 8179, 8209, 8238, + 8268, 8298, 8328, 8357, 8387, 8416, 8445, 8475, + 8504, 8533, 8563, 8592, 8622, 8652, 8682, 8711, + 8741, 8771, 8800, 8830, 8859, 8888, 8917, 8947, + 8976, 9006, 9036, 9065, 9095, 9125, 9155, 9184, + 9214, 9243, 9272, 9301, 9331, 9360, 9390, 9419, + 9449, 9479, 9509, 9538, 9568, 9597, 9627, 9656, + 9685, 9715, 9744, 9774, 9803, 9833, 9863, 9893, + 9922, 9952, 9981, 10011, 10040, 10069, 10099, 10128, + 10158, 10187, 10217, 10247, 10276, 10306, 10336, 10365, + 10395, 10424, 10454, 10483, 10512, 10542, 10571, 10601, + 10630, 10660, 10690, 10719, 10749, 10778, 10808, 10837, + 10867, 10896, 10926, 10955, 10985, 11014, 11044, 11073, + 11103, 11132, 11162, 11192, 11221, 11251, 11281, 11310, + 11339, 11369, 11398, 11428, 11457, 11487, 11516, 11546, + 11576, 11605, 11635, 11665, 11694, 11723, 11753, 11782, + 11811, 11841, 11870, 11900, 11930, 11959, 11989, 12019, + 12049, 12078, 12108, 12137, 12166, 12195, 12225, 12254, + 12284, 12313, 12343, 12373, 12403, 12432, 12462, 12491, + 12521, 12550, 12579, 12609, 12638, 12668, 12697, 12727, + 12757, 12787, 12816, 12846, 12875, 12905, 12934, 12963, + 12993, 13022, 13052, 13081, 13111, 13141, 13170, 13200, + 13230, 13259, 13289, 13318, 13347, 13377, 13406, 13436, + 13465, 13495, 13524, 13554, 13584, 13613, 13643, 13673, + 13702, 13731, 13761, 13790, 13820, 13849, 13879, 13908, + 13938, 13967, 13997, 14027, 14056, 14086, 14115, 14145, + 14174, 14204, 14233, 14263, 14292, 14321, 14351, 14381, + 14410, 14440, 14470, 14499, 14529, 14558, 14588, 14617, + 14647, 14676, 14706, 14735, 14764, 14794, 14824, 14853, + 14883, 14913, 14943, 14972, 15001, 15031, 15060, 15089, + 15119, 15148, 15178, 15207, 15237, 15267, 15297, 15326, + 15356, 15385, 15415, 15444, 15473, 15503, 15532, 15562, + 15591, 15621, 15651, 15681, 15710, 15740, 15769, 15799, + 15828, 15857, 15887, 15916, 15946, 15975, 16005, 16035, + 16064, 16094, 16124, 16153, 16183, 16212, 16241, 16271, + 16300, 16330, 16359, 16389, 16418, 16448, 16478, 16508, + 16537, 16567, 16596, 16625, 16655, 16684, 16714, 16743, + 16773, 16802, 16832, 16862, 16891, 16921, 16950, 16980, + 17009, 17039, 17068, 17098, 17127, 17157, 17186, 17216, + 17245, 17275, 17304, 17334, 17364, 17393, 17423, 17452, + 17482, 17511, 17541, 17570, 17600, 17629, 17659, 17688, + 17718, 17747, 17777, 17807, 17836, 17866, 17895, 17925, + 17954, 17983, 18013, 18042, 18072, 18101, 18131, 18161, + 18191, 18221, 18250, 18279, 18309, 18338, 18367, 18397, + 18426, 18456, 18485, 18515, 18545, 18575, 18604, 18634, + 18663, 18693, 18722, 18751, 18781, 18810, 18839, 18869, + 18899, 18928, 18958, 18988, 19018, 19047, 19077, 19106, + 19135, 19165, 19194, 19223, 19253, 19283, 19312, 19342, + 19372, 19402, 19431, 19461, 19490, 19519, 19549, 19578, + 19607, 19637, 19667, 19697, 19726, 19756, 19785, 19815, + 19845, 19874, 19903, 19933, 19962, 19992, 20021, 20051, + 20080, 20110, 20139, 20169, 20199, 20228, 20258, 20287, + 20317, 20346, 20376, 20405, 20435, 20464, 20494, 20523, + 20553, 20582, 20612, 20642, 20671, 20701, 20730, 20760, + 20789, 20819, 20848, 20877, 20907, 20936, 20966, 20996, + 21025, 21055, 21085, 21114, 21144, 21173, 21203, 21232, + 21261, 21291, 21320, 21350, 21379, 21409, 21439, 21468, + 21498, 21528, 21557, 21587, 21616, 21645, 21675, 21704, + 21734, 21763, 21793, 21822, 21852, 21882, 21912, 21941, + 21971, 22000, 22029, 22059, 22088, 22117, 22147, 22177, + 22206, 22236, 22266, 22296, 22325, 22355, 22384, 22413, + 22443, 22472, 22501, 22531, 22560, 22590, 22620, 22650, + 22679, 22709, 22739, 22768, 22797, 22827, 22856, 22885, + 22915, 22944, 22974, 23004, 23033, 23063, 23093, 23122, + 23152, 23181, 23211, 23240, 23270, 23299, 23328, 23358, + 23388, 23417, 23447, 23476, 23506, 23536, 23565, 23595, + 23624, 23654, 23683, 23713, 23742, 23771, 23801, 23831, + 23860, 23890, 23919, 23949, 23979, 24008, 24038, 24067, + 24097, 24126, 24155, 24185, 24214, 24244, 24273, 24303, + 24333, 24362, 24392, 24422, 24451, 24481, 24510, 24539, + 24569, 24598, 24628, 24657, 24687, 24716, 24746, 24776, + 24806, 24835, 24865, 24894, 24923, 24953, 24982, 25011, + 25041, 25071, 25100, 25130, 25160, 25190, 25219, 25249, + 25278, 25307, 25337, 25366, 25395, 25425, 25454, 25484, + 25514, 25544, 25573, 25603, 25633, 25662, 25691, 25721, + 25750, 25779, 25809, 25838, 25868, 25898, 25927, 25957, + 25987, 26017, 26046, 26075, 26105, 26134, 26163, 26193, + 26222, 26252, 26282, 26311, 26341, 26371, 26400, 26430, + 26459, 26489, 26518, 26548, 26577, 26606, 26636, 26665, + 26695, 26725, 26754, 26784, 26814, 26843, 26873, 26902, + 26932, 26961, 26991, 27020, 27049, 27079, 27108, 27138, + 27168, 27197, 27227, 27256, 27286, 27316, 27345, 27375, + 27404, 27433, 27463, 27492, 27522, 27551, 27581, 27611, + 27640, 27670, 27700, 27729, 27759, 27788, 27817, 27847, + 27876, 27905, 27935, 27965, 27994, 28024, 28054, 28084, + 28113, 28143, 28172, 28201, 28231, 28260, 28289, 28319, + 28348, 28378, 28408, 28438, 28467, 28497, 28527, 28556, + 28585, 28615, 28644, 28673, 28703, 28732, 28762, 28792, + 28821, 28851, 28881, 28911, 28940, 28969, 28999, 29028, + 29057, 29087, 29116, 29146, 29175, 29205, 29235, 29265, + 29294, 29324, 29353, 29383, 29412, 29441, 29471, 29500, + 29530, 29559, 29589, 29619, 29648, 29678, 29708, 29737, + 29767, 29796, 29825, 29855, 29884, 29914, 29943, 29973, + 30002, 30032, 30062, 30091, 30121, 30151, 30180, 30210, + 30239, 30268, 30298, 30327, 30357, 30386, 30416, 30445, + 30475, 30505, 30534, 30564, 30594, 30623, 30653, 30682, + 30711, 30741, 30770, 30800, 30829, 30859, 30888, 30918, + 30948, 30977, 31007, 31037, 31066, 31095, 31125, 31154, + 31183, 31213, 31242, 31272, 31302, 31332, 31361, 31391, + 31421, 31450, 31479, 31509, 31538, 31567, 31597, 31626, + 31656, 31686, 31715, 31745, 31775, 31805, 31834, 31863, + 31893, 31922, 31951, 31981, 32010, 32040, 32069, 32099, + 32129, 32159, 32188, 32218, 32247, 32277, 32306, 32335, + 32365, 32394, 32424, 32453, 32483, 32513, 32542, 32572, + 32602, 32631, 32661, 32690, 32719, 32749, 32778, 32808, + 32837, 32867, 32896, 32926, 32956, 32986, 33015, 33045, + 33074, 33103, 33133, 33162, 33192, 33221, 33251, 33280, + 33310, 33340, 33369, 33399, 33428, 33458, 33487, 33517, + 33546, 33576, 33605, 33635, 33664, 33694, 33723, 33753, + 33782, 33812, 33842, 33871, 33901, 33931, 33960, 33989, + 34019, 34048, 34078, 34107, 34136, 34166, 34196, 34226, + 34255, 34285, 34315, 34344, 34373, 34403, 34432, 34461, + 34491, 34520, 34550, 34580, 34609, 34639, 34669, 34699, + 34728, 34757, 34787, 34816, 34845, 34875, 34904, 34934, + 34963, 34993, 35023, 35053, 35082, 35112, 35141, 35171, + 35200, 35229, 35259, 35288, 35318, 35347, 35377, 35407, + 35437, 35466, 35496, 35525, 35555, 35584, 35613, 35643, + 35672, 35702, 35731, 35761, 35791, 35820, 35850, 35880, + 35909, 35939, 35968, 35997, 36027, 36056, 36086, 36115, + 36145, 36174, 36204, 36234, 36263, 36293, 36322, 36352, + 36381, 36411, 36440, 36470, 36499, 36529, 36558, 36588, + 36617, 36647, 36677, 36706, 36736, 36765, 36795, 36824, + 36854, 36883, 36913, 36942, 36972, 37001, 37031, 37060, + 37090, 37120, 37149, 37179, 37208, 37238, 37267, 37297, + 37326, 37355, 37385, 37414, 37444, 37474, 37503, 37533, + 37563, 37592, 37622, 37651, 37681, 37710, 37739, 37769, + 37798, 37828, 37857, 37887, 37917, 37947, 37976, 38006, + 38035, 38065, 38094, 38123, 38153, 38182, 38212, 38241, + 38271, 38301, 38331, 38360, 38390, 38419, 38449, 38478, + 38507, 38537, 38566, 38595, 38625, 38655, 38685, 38714, + 38744, 38774, 38803, 38833, 38862, 38891, 38921, 38950, + 38980, 39009, 39039, 39068, 39098, 39128, 39157, 39187, + 39217, 39246, 39275, 39305, 39334, 39364, 39393, 39423, + 39452, 39482, 39511, 39541, 39571, 39600, 39630, 39659, + 39689, 39718, 39748, 39777, 39807, 39836, 39866, 39895, + 39925, 39954, 39984, 40014, 40043, 40073, 40102, 40132, + 40161, 40191, 40220, 40249, 40279, 40308, 40338, 40368, + 40397, 40427, 40457, 40486, 40516, 40545, 40575, 40604, + 40633, 40663, 40692, 40722, 40751, 40781, 40811, 40841, + 40870, 40900, 40929, 40959, 40988, 41017, 41047, 41076, + 41106, 41135, 41165, 41195, 41225, 41254, 41284, 41313, + 41343, 41372, 41401, 41431, 41460, 41489, 41519, 41549, + 41578, 41608, 41638, 41668, 41697, 41727, 41756, 41785, + 41815, 41844, 41873, 41903, 41933, 41962, 41992, 42022, + 42052, 42081, 42111, 42140, 42169, 42199, 42228, 42257, + 42287, 42316, 42346, 42376, 42406, 42435, 42465, 42494, + 42524, 42553, 42583, 42612, 42642, 42671, 42701, 42730, + 42760, 42789, 42819, 42849, 42878, 42908, 42937, 42967, + 42996, 43026, 43055, 43085, 43114, 43144, 43173, 43203, + 43232, 43262, 43292, 43321, 43351, 43380, 43410, 43439, + 43469, 43498, 43527, 43557, 43586, 43616, 43646, 43675, + 43705, 43735, 43764, 43794, 43823, 43853, 43882, 43911, + 43941, 43970, 44000, 44029, 44059, 44089, 44118, 44148, + 44178, 44207, 44237, 44266, 44295, 44325, 44354, 44383, + 44413, 44443, 44472, 44502, 44532, 44562, 44591, 44621, + 44650, 44679, 44709, 44738, 44767, 44797, 44826, 44856, + 44886, 44916, 44946, 44975, 45005, 45034, 45063, 45093, + 45122, 45151, 45181, 45210, 45240, 45270, 45300, 45329, + 45359, 45389, 45418, 45447, 45477, 45506, 45535, 45565, + 45594, 45624, 45654, 45683, 45713, 45743, 45772, 45802, + 45831, 45861, 45890, 45920, 45949, 45978, 46008, 46038, + 46067, 46097, 46126, 46156, 46186, 46215, 46245, 46274, + 46304, 46333, 46363, 46392, 46421, 46451, 46480, 46510, + 46540, 46569, 46599, 46629, 46658, 46688, 46717, 46747, + 46776, 46805, 46835, 46864, 46894, 46923, 46953, 46983, + 47012, 47042, 47072, 47101, 47131, 47160, 47189, 47219, + 47248, 47278, 47307, 47337, 47366, 47396, 47426, 47456, + 47485, 47515, 47544, 47573, 47603, 47632, 47661, 47691, + 47720, 47750, 47780, 47810, 47840, 47869, 47899, 47928, + 47957, 47987, 48016, 48045, 48075, 48104, 48134, 48164, + 48194, 48223, 48253, 48283, 48312, 48341, 48371, 48400, + 48429, 48459, 48488, 48518, 48548, 48577, 48607, 48637, + 48666, 48696, 48725, 48755, 48784, 48813, 48843, 48872, + 48902, 48931, 48961, 48991, 49021, 49050, 49080, 49109, + 49139, 49168, 49197, 49227, 49256, 49286, 49315, 49345, + 49375, 49404, 49434, 49463, 49493, 49523, 49552, 49582, + 49611, 49640, 49670, 49699, 49729, 49758, 49788, 49817, + 49847, 49877, 49906, 49936, 49966, 49995, 50025, 50054, + 50083, 50113, 50142, 50172, 50201, 50231, 50261, 50290, + 50320, 50350, 50379, 50409, 50438, 50467, 50497, 50526, + 50555, 50585, 50615, 50644, 50674, 50704, 50734, 50763, + 50792, 50822, 50851, 50881, 50910, 50939, 50969, 50998, + 51028, 51058, 51088, 51117, 51147, 51177, 51206, 51235, + 51265, 51294, 51323, 51353, 51382, 51412, 51442, 51471, + 51501, 51531, 51561, 51590, 51619, 51649, 51678, 51707, + 51737, 51766, 51796, 51825, 51855, 51885, 51915, 51944, + 51974, 52003, 52033, 52062, 52091, 52121, 52150, 52180, + 52209, 52239, 52269, 52298, 52328, 52358, 52387, 52417, + 52446, 52475, 52505, 52534, 52564, 52593, 52623, 52652, + 52682, 52712, 52741, 52771, 52800, 52830, 52860, 52889, + 52918, 52948, 52977, 53007, 53036, 53066, 53095, 53125, + 53155, 53184, 53214, 53244, 53273, 53303, 53332, 53361, + 53391, 53420, 53450, 53479, 53509, 53538, 53568, 53598, + 53627, 53657, 53687, 53716, 53745, 53775, 53804, 53833, + 53863, 53892, 53922, 53952, 53982, 54011, 54041, 54071, + 54100, 54129, 54159, 54188, 54217, 54247, 54276, 54306, + 54336, 54365, 54395, 54425, 54455, 54484, 54513, 54543, + 54572, 54601, 54631, 54660, 54690, 54719, 54749, 54779, + 54809, 54838, 54868, 54897, 54927, 54956, 54985, 55015, + 55044, 55074, 55103, 55133, 55163, 55192, 55222, 55252, + 55281, 55311, 55340, 55369, 55399, 55428, 55458, 55487, + 55517, 55546, 55576, 55606, 55635, 55665, 55695, 55724, + 55753, 55783, 55812, 55842, 55871, 55901, 55930, 55960, + 55989, 56019, 56049, 56078, 56108, 56137, 56167, 56196, + 56226, 56255, 56285, 56314, 56344, 56373, 56403, 56432, + 56462, 56492, 56521, 56551, 56581, 56610, 56639, 56669, + 56698, 56727, 56757, 56786, 56816, 56846, 56876, 56905, + 56935, 56965, 56994, 57023, 57053, 57082, 57111, 57141, + 57170, 57200, 57230, 57259, 57289, 57319, 57349, 57378, + 57407, 57437, 57466, 57495, 57525, 57554, 57584, 57613, + 57643, 57673, 57703, 57732, 57762, 57791, 57821, 57850, + 57879, 57909, 57938, 57968, 57997, 58027, 58057, 58087, + 58116, 58146, 58175, 58205, 58234, 58263, 58293, 58322, + 58352, 58381, 58411, 58440, 58470, 58500, 58530, 58559, + 58589, 58618, 58647, 58677, 58706, 58736, 58765, 58795, + 58824, 58854, 58884, 58913, 58943, 58972, 59002, 59031, + 59061, 59090, 59120, 59149, 59179, 59208, 59238, 59267, + 59297, 59327, 59356, 59386, 59415, 59445, 59474, 59504, + 59533, 59563, 59592, 59622, 59651, 59681, 59710, 59740, + 59770, 59799, 59829, 59858, 59888, 59917, 59947, 59976, + 60005, 60035, 60064, 60094, 60124, 60153, 60183, 60213, + 60242, 60272, 60301, 60331, 60360, 60389, 60419, 60448, + 60478, 60507, 60537, 60567, 60597, 60626, 60656, 60685, + 60715, 60744, 60773, 60803, 60832, 60862, 60891, 60921, + 60951, 60981, 61010, 61040, 61069, 61099, 61128, 61157, + 61187, 61216, 61245, 61275, 61305, 61334, 61364, 61394, + 61424, 61453, 61483, 61512, 61541, 61571, 61600, 61629, + 61659, 61689, 61718, 61748, 61778, 61807, 61837, 61867, + 61896, 61925, 61955, 61984, 62014, 62043, 62073, 62102, + 62132, 62161, 62191, 62221, 62250, 62280, 62309, 62339, + 62368, 62398, 62427, 62457, 62486, 62516, 62545, 62575, + 62604, 62634, 62664, 62693, 62723, 62752, 62782, 62811, + 62841, 62870, 62899, 62929, 62958, 62988, 63018, 63047, + 63077, 63107, 63136, 63166, 63195, 63225, 63254, 63283, + 63313, 63342, 63372, 63401, 63431, 63461, 63491, 63520, + 63550, 63579, 63609, 63638, 63667, 63697, 63726, 63756, + 63785, 63815, 63845, 63875, 63904, 63934, 63963, 63993, + 64022, 64051, 64081, 64110, 64139, 64169, 64199, 64228, + 64258, 64288, 64318, 64347, 64377, 64406, 64435, 64465, + 64494, 64523, 64553, 64583, 64612, 64642, 64672, 64702, + 64731, 64761, 64790, 64819, 64849, 64878, 64907, 64937, + 64966, 64996, 65026, 65056, 65085, 65115, 65144, 65174, + 65203, 65233, 65262, 65292, 65321, 65350, 65380, 65410, + 65439, 65469, 65499, 65528, 65558, 65587, 65617, 65646, + 65676, 65705, 65735, 65764, 65793, 65823, 65853, 65882, + 65912, 65941, 65971, 66001, 66030, 66060, 66089, 66119, + 66148, 66177, 66207, 66236, 66266, 66295, 66325, 66355, + 66385, 66414, 66444, 66473, 66503, 66532, 66561, 66591, + 66620, 66650, 66679, 66709, 66739, 66768, 66798, 66828, + 66857, 66887, 66916, 66945, 66975, 67004, 67033, 67063, + 67093, 67122, 67152, 67182, 67212, 67241, 67271, 67300, + 67329, 67359, 67388, 67417, 67447, 67476, 67506, 67536, + 67566, 67596, 67625, 67655, 67684, 67713, 67743, 67772, + 67801, 67831, 67860, 67890, 67920, 67950, 67979, 68009, + 68039, 68068, 68097, 68127, 68156, 68185, 68215, 68244, + 68274, 68304, 68333, 68363, 68393, 68422, 68452, 68481, + 68511, 68540, 68569, 68599, 68628, 68658, 68687, 68717, + 68747, 68776, 68806, 68836, 68865, 68895, 68924, 68954, + 68983, 69012, 69042, 69071, 69101, 69130, 69160, 69190, + 69219, 69249, 69279, 69308, 69338, 69367, 69397, 69426, + 69455, 69485, 69514, 69544, 69573, 69603, 69633, 69662, + 69692, 69722, 69751, 69781, 69810, 69839, 69869, 69898, + 69927, 69957, 69987, 70016, 70046, 70076, 70106, 70135, + 70165, 70194, 70223, 70253, 70282, 70311, 70341, 70370, + 70400, 70430, 70460, 70490, 70519, 70549, 70578, 70607, + 70637, 70666, 70695, 70725, 70754, 70784, 70814, 70844, + 70873, 70903, 70933, 70962, 70991, 71021, 71050, 71079, + 71109, 71138, 71168, 71198, 71227, 71257, 71287, 71316, + 71346, 71375, 71405, 71434, 71463, 71493, 71522, 71552, + 71581, 71611, 71641, 71671, 71700, 71730, 71759, 71789, + 71818, 71847, 71877, 71906, 71936, 71965, 71995, 72025, + 72054, 72084, 72113, 72143, 72173, 72202, 72232, 72261, + 72290, 72320, 72349, 72379, 72408, 72438, 72467, 72497, + 72527, 72556, 72586, 72616, 72645, 72675, 72704, 72733, + 72763, 72792, 72822, 72851, 72881, 72911, 72940, 72970, + 73000, 73029, 73059, 73088, 73117, 73147, 73176, 73205, + 73235, 73264, 73294, 73324, 73354, 73384, 73413, 73443, + 73472, 73501, 73531, 73560, 73589, 73619, 73648, 73678, + 73708, 73738, 73767, 73797, 73827, 73856, 73885, 73915, + 73944, 73973, 74003, 74032, 74062, 74092, 74121, 74151, + 74181, 74210, 74240, 74269, 74299, 74328, 74357, 74387, + 74416, 74446, 74475, 74505, 74535, 74565, 74594, 74624, + 74653, 74683, 74712, 74741, 74771, 74800, 74830, 74859, + 74889, 74919, 74948, 74978, 75008, 75037, 75067, 75096, + 75125, 75155, 75184, 75214, 75243, 75273, 75302, 75332, + 75362, 75391, 75421, 75450, 75479, 75509, 75539, 75568, + 75598, 75627, 75657, 75686, 75716, 75745, 75775, 75805, + 75834, 75864, 75893, 75923, 75953, 75982, 76011, 76041, + 76070, 76099, 76129, 76159, 76188, 76218, 76248, 76277, + 76307, 76337, 76366, 76395, 76425, 76454, 76483, 76513, + 76542, 76572, 76602, 76632, 76661, 76691, 76721, 76750, + 76779, 76809, 76838, 76867, 76897, 76926, 76956, 76986, + 77015, 77045, 77075, 77105, 77134, 77163, 77193, 77222, + 77251, 77281, 77311, 77340, 77369, 77399, 77429, 77459, + 77488, 77518, 77547, 77577, 77606, 77635, 77665, 77694, + 77724, 77753, 77783, 77813, 77842, 77872, 77902, 77931, + 77961, 77990, 78019, 78049, 78078, 78108, 78137, 78167, + 78196, 78226, 78256, 78285, 78315, 78344, 78374, 78403, + 78433, 78462, 78492, 78521, 78551, 78580, 78610, 78639, + 78669, 78699, 78728, 78758, 78787, 78817, 78846, 78876, + 78905, 78935, 78964, 78994, 79023, 79053, 79082, 79112, + 79142, 79171, 79201, 79230, 79260, 79289, 79319, 79348, + 79377, 79407, 79436, 79466, 79496, 79526, 79555, 79585, + 79615, 79644, 79673, 79703, 79732, 79761, 79791, 79820, + 79850, 79880, 79909, 79939, 79969, 79998, 80028, 80057, + 80087, 80116, 80145, 80175, 80204, 80234, 80263, 80293, + 80323, 80353, 80382, 80412, 80441, 80471, 80500, 80529, + 80559, 80588, 80618, 80647, 80677, 80707, 80737, 80766, + 80796, 80825, 80855, 80884, 80913, 80943, 80972, 81002, + 81031, 81061, 81090, 81120, 81150, 81180, 81209, 81239, + 81268, 81297, 81327, 81356, 81386, 81415, 81445, 81474, + 81504, 81534, 81563, 81593, 81622, 81652, 81681, 81711, + 81740, 81770, 81799, 81829, 81858, 81888, 81917, 81947, + 81977, 82006, 82036, 82065, 82095, 82124, 82154, 82183, + 82213, 82242, 82271, 82301, 82331, 82360, 82390, 82420, + 82449, 82479, 82508, 82538, 82567, 82597, 82626, 82655, + 82685, 82714, 82744, 82774, 82803, 82833, 82863, 82892, + 82922, 82951, 82981, 83010, 83039, 83069, 83098, 83128, + 83157, 83187, 83217, 83247, 83276, 83306, 83335, 83365, + 83394, 83423, 83453, 83482, 83511, 83541, 83571, 83601, + 83631, 83660, 83690, 83719, 83749, 83778, 83807, 83837, + 83866, 83895, 83925, 83955, 83984, 84014, 84044, 84074, + 84103, 84133, 84162, 84191, 84221, 84250, 84279, 84309, + 84339, 84368, 84398, 84428, 84457, 84487, 84516, 84546, + 84575, 84605, 84634, 84664, 84693, 84723, 84752, 84782, + 84811, 84841, 84871, 84900, 84930, 84959, 84989, 85018, + 85048, 85077, 85107, 85136, 85166, 85195, 85225, 85254, + 85284, 85314, 85343, 85373, 85402, 85432, 85461, 85491, + 85520, 85549, 85579, 85608, 85638, 85668, 85697, 85727, + 85757, 85786, 85816, 85845, 85875, 85904, 85933, 85963, + 85992, 86022, 86051, 86081, 86111, 86141, 86170, 86200, + 86229, 86259, 86288, 86317, 86347, 86376, 86405, 86435, + 86465, 86495, 86525, 86554, 86584, 86613, 86643, 86672, + 86701, 86731, 86760, 86789, 86819, 86849, 86878, 86908, + 86938, 86968, 86997, 87027, 87056, 87085, 87115, 87144, + 87173, 87203, 87233, 87262, 87292, 87322, 87352, 87381, + 87411, 87440, 87469, 87499, 87528, 87557, 87587, 87616, + 87646, 87676, 87706, 87735, 87765, 87794, 87824, 87853, + 87883, 87912, 87941, 87971, 88000, 88030, 88060, 88089, + 88119, 88149, 88178, 88208, 88237, 88267, 88296, 88326, + 88355, 88384, 88414, 88443, 88473, 88503, 88532, 88562, + 88591, 88621, 88651, 88680, 88710, 88739, 88769, 88798, + 88827, 88857, 88886, 88916, 88945, 88975, 89005, 89035, + 89064, 89094, 89123, 89153, 89182, 89211, 89241, 89270, + 89300, 89329, 89359, 89389, 89418, 89448, 89478, 89507, + 89537, 89566, 89595, 89625, 89654, 89683, 89713, 89743, + 89772, 89802, 89832, 89862, 89891, 89921, 89950, 89979, + 90009, 90038, 90067, 90097, 90126, 90156, 90186, 90216, + 90246, 90275, 90305, 90334, 90363, 90393, 90422, 90451, + 90481, 90510, 90540, 90570, 90600, 90629, 90659, 90688, + 90718, 90747, 90777, 90806, 90835, 90865, 90894, 90924, + 90954, 90983, 91013, 91043, 91072, 91102, 91131, 91161, + 91190, 91219, 91249, 91278, 91308, 91337, 91367, 91397, + 91426, 91456, 91486, 91515, 91545, 91574, 91604, 91633, + 91662, 91692, 91721, 91751, 91780, 91810, 91840, 91869, + 91899, 91929, 91958, 91988, 92017, 92047, 92076, 92105, + 92135, 92164, 92194, 92223, 92253, 92283, 92312, 92342, + 92372, 92401, 92431, 92460, 92489, 92519, 92548, 92577, + 92607, 92637, 92666, 92696, 92726, 92756, 92785, 92815, + 92844, 92873, 92903, 92932, 92961, 92991, 93020, 93050, + 93080, 93110, 93140, 93169, 93199, 93228, 93257, 93287, + 93316, 93345, 93375, 93404, 93434, 93464, 93494, 93523, + 93553, 93583, 93612, 93641, 93671, 93700, 93729, 93759, + 93788, 93818, 93848, 93877, 93907, 93937, 93966, 93996, + 94025, 94055, 94084, 94113, 94143, 94172, 94202, 94231, + 94261, 94291, 94320, 94350, 94380, 94409, 94439, 94468, + 94497, 94527, 94556, 94586, 94615, 94645, 94675, 94704, + 94734, 94763, 94793, 94823, 94852, 94882, 94911, 94940, + 94970, 94999, 95029, 95058, 95088, 95117, 95147, 95177, + 95206, 95236, 95266, 95295, 95325, 95354, 95383, 95413, + 95442, 95472, 95501, 95531, 95561, 95591, 95620, 95650, + 95679, 95709, 95738, 95767, 95797, 95826, 95855, 95885, + 95914, 95944, 95974, 96004, 96034, 96063, 96093, 96122, + 96151, 96181, 96210, 96239, 96269, 96298, 96328, 96358, + 96388, 96417, 96447, 96477, 96506, 96535, 96565, 96594, + 96623, 96653, 96682, 96712, 96742, 96771, 96801, 96831, + 96860, 96890, 96919, 96949, 96978, 97007, 97037, 97066, + 97096, 97125, 97155, 97185, 97215, 97244, 97274, 97303, + 97333, 97362, 97391, 97421, 97450, 97480, 97509, 97539, + 97569, 97598, 97628, 97658, 97687, 97717, 97746, 97775, + 97805, 97834, 97864, 97893, 97923, 97952, 97982, 98012, + 98041, 98071, 98100, 98130, 98159, 98189, 98218, 98248, + 98277, 98307, 98336, 98366, 98395, 98425, 98455, 98484, + 98514, 98543, 98573, 98602, 98632, 98661, 98691, 98720, + 98749, 98779, 98809, 98838, 98868, 98898, 98927, 98957, + 98986, 99016, 99045, 99075, 99104, 99133, 99163, 99192, + 99222, 99252, 99282, 99311, 99341, 99371, 99400, 99429, + 99459, 99488, 99517, 99547, 99576, 99606, 99636, 99665, + 99695, 99725, 99754, 99784, 99813, 99843, 99872, 99901, + 99931, 99960, 99990, 100019, 100049, 100079, 100109, 100138, + 100168, 100197, 100227, 100256, 100285, 100315, 100344, 100374, + 100403, 100433, 100463, 100492, 100522, 100552, 100581, 100611, + 100640, 100669, 100699, 100728, 100758, 100787, 100817, 100846, + 100876, 100906, 100935, 100965, 100994, 101024, 101053, 101083, + 101112, 101142, 101171, 101201, 101230, 101260, 101289, 101319, + 101349, 101378, 101408, 101437, 101467, 101496, 101526, 101555, + 101585, 101614, 101644, 101673, 101703, 101732, 101762, 101792, + 101821, 101851, 101880, 101910, 101939, 101969, 101998, 102027, + 102057, 102086, 102116, 102146, 102176, 102205, 102235, 102264, + 102294, 102323, 102353, 102382, 102411, 102441, 102470, 102500, + 102530, 102559, 102589, 102619, 102648, 102678, 102707, 102737, + 102766, 102795, 102825, 102854, 102884, 102913, 102943, 102973, + 103003, 103032, 103062, 103091, 103121, 103150, 103179, 103209, + 103238, 103268, 103297, 103327, 103357, 103386, 103416, 103446, + 103475, 103505, 103534, 103563, 103593, 103622, 103651, 103681, + 103711, 103740, 103770, 103800, 103830, 103859, 103889, 103918, + 103947, 103977, 104006, 104036, 104065, 104095, 104124, 104154, + 104184, 104213, 104243, 104272, 104302, 104331, 104361, 104390, + 104420, 104449, 104479, 104508, 104538, 104567, 104597, 104627, + 104656, 104686, 104716, 104745, 104774, 104804, 104833, 104863, + 104892, 104921, 104951, 104981, 105010, 105040, 105070, 105099, + 105129, 105158, 105188, 105217, 105247, 105276, 105305, 105335, + 105364, 105394, 105424, 105453, 105483, 105513, 105542, 105572, + 105601, 105631, 105660, 105689, 105719, 105748, 105778, 105807, + 105837, 105867, 105897, 105926, 105956, 105985, 106015, 106044, + 106073, 106103, 106132, 106161, 106191, 106221, 106251, 106280, + 106310, 106340, 106369, 106399, 106428, 106457, 106487, 106516, + 106545, 106575, 106605, 106634, 106664, 106694, 106724, 106753, + 106783, 106812, 106841, 106871, 106900, 106929, 106959, 106989, + 107018, 107048, 107078, 107107, 107137, 107166, 107196, 107225, + 107255, 107284, 107313, 107343, 107372, 107402, 107432, 107461, + 107491, 107521, 107550, 107580, 107609, 107639, 107668, 107698, + 107727, 107756, 107786, 107816, 107845, 107875, 107904, 107934, + 107964, 107993, 108023, 108052, 108082, 108111, 108140, 108170, + 108199, 108229, 108258, 108288, 108318, 108347, 108377, 108407, + 108436, 108466, 108495, 108525, 108554, 108583, 108613, 108642, + 108672, 108701, 108731, 108761, 108791, 108820, 108850, 108879, + 108909, 108938, 108967, 108997, 109026, 109055, 109085, 109115, + 109145, 109174, 109204, 109234, 109263, 109293, 109322, 109351, + 109381, 109410, 109439, 109469, 109499, 109528, 109558, 109588, + 109618, 109647, 109677, 109706, 109735, 109765, 109794, 109823, + 109853, 109882, 109912, 109942, 109972, 110001, 110031, 110061, + 110090, 110119, 110149, 110178, 110207, 110237, 110266, 110296, + 110326, 110356, 110385, 110415, 110444, 110474, 110503, 110533, + 110562, 110591, 110621, 110650, 110680, 110710, 110739, 110769, + 110798, 110828, 110858, 110887, 110917, 110946, 110976, 111005, + 111034, 111064, 111093, 111123, 111153, 111182, 111212, 111241, + 111271, 111301, 111330, 111360, 111389, 111418, 111448, 111477, + 111507, 111536, 111566, 111595, 111625, 111655, 111685, 111714, + 111744, 111773, 111803, 111832, 111861, 111891, 111920, 111950, + 111979, 112009, 112039, 112068, 112098, 112128, 112157, 112187, + 112216, 112245, 112275, 112304, 112333, 112363, 112393, 112423, + 112452, 112482, 112512, 112541, 112571, 112600, 112629, 112659, + 112688, 112717, 112747, 112776, 112806, 112836, 112866, 112896, + 112925, 112955, 112984, 113013, 113043, 113072, 113101, 113131, + 113160, 113190, 113220, 113250, 113279, 113309, 113338, 113368, + 113397, 113427, 113456, 113485, 113515, 113544, 113574, 113604, + 113633, 113663, 113693, 113722, 113752, 113781, 113811, 113840, + 113869, 113899, 113928, 113958, 113987, 114017, 114047, 114076, + 114106, 114136, 114165, 114195, 114224, 114253, 114283, 114312, + 114342, 114371, 114401, 114430, 114460, 114490, 114519, 114549, + 114579, 114608, 114638, 114667, 114696, 114726, 114755, 114785, + 114814, 114844, 114873, 114903, 114933, 114962, 114992, 115022, + 115051, 115081, 115110, 115139, 115169, 115198, 115227, 115257, + 115287, 115316, 115346, 115376, 115406, 115435, 115465, 115494, + 115523, 115553, 115582, 115611, 115641, 115670, 115700, 115730, + 115760, 115789, 115819, 115849, 115878, 115907, 115937, 115966, + 115995, 116025, 116054, 116084, 116114, 116144, 116174, 116203, + 116233, 116262, 116291, 116321, 116350, 116379, 116409, 116439, + 116468, 116498, 116527, 116557, 116587, 116616, 116646, 116675, + 116705, 116734, 116763, 116793, 116822, 116852, 116881, 116911, + 116941, 116970, 117000, 117030, 117059, 117089, 117118, 117147, + 117177, 117206, 117236, 117265, 117295, 117324, 117354, 117384, + 117413, 117443, 117472, 117502, 117531, 117561, 117590, 117620, + 117649, 117679, 117708, 117738, 117767, 117797, 117827, 117856, + 117886, 117916, 117945, 117974, 118004, 118033, 118063, 118092, + 118122, 118151, 118181, 118210, 118240, 118270, 118300, 118329, + 118359, 118388, 118417, 118447, 118476, 118505, 118535, 118564, + 118594, 118624, 118654, 118683, 118713, 118743, 118772, 118801, + 118831, 118860, 118889, 118919, 118948, 118978, 119008, 119038, + 119067, 119097, 119127, 119156, 119185, 119215, 119244, 119273, + 119303, 119332, 119362, 119392, 119421, 119451, 119481, 119510, + 119540, 119569, 119599, 119628, 119657, 119687, 119716, 119746, + 119775, 119805, 119835, 119865, 119894, 119924, 119953, 119983, + 120012, 120041, 120071, 120100, 120130, 120159, 120189, 120219, + 120248, 120278, 120307, 120337, 120366, 120396, 120425, 120455, + 120484, 120514, 120543, 120573, 120602, 120632, 120662, 120691, + 120721, 120750, 120780, 120809, 120839, 120868, 120898, 120927, + 120957, 120986, 121016, 121045, 121075, 121105, 121134, 121164, + 121193, 121223, 121252, 121282, 121311, 121341, 121370, 121399, + 121429, 121459, 121488, 121518, 121548, 121577, 121607, 121636, + 121666, 121695, 121725, 121754, 121783, 121813, 121842, 121872, + 121902, 121932, 121961, 121991, 122020, 122050, 122079, 122109, + 122138, 122167, 122197, 122226, 122256, 122286, 122315, 122345, + 122375, 122404, 122434, 122463, 122493, 122522, 122551, 122581, + 122610, 122640, 122669, 122699, 122729, 122759, 122789, 122818, + 122847, 122877, 122906, 122935, 122965, 122994, 123024, 123053, + 123083, 123113, 123142, 123172, 123202, 123231, 123261, 123290, + 123319, 123349, 123378, 123408, 123437, 123467, 123496, 123526, + 123556, 123585, 123615, 123644, 123674, 123703, 123733, 123762, + 123792, 123821, 123851, 123880, 123909, 123939, 123969, 123999, + 124028, 124058, 124087, 124117, 124146, 124176, 124205, 124235, + 124264, 124294, 124323, 124353, 124382, 124412, 124442, 124471, + 124501, 124530, 124560, 124589, 124619, 124648, 124677, 124707, + 124736, 124766, 124796, 124826, 124855, 124885, 124914, 124944, + 124973, 125003, 125032, 125061, 125091, 125120, 125150, 125180, + 125209, 125239, 125269, 125298, 125328, 125357, 125387, 125416, + 125445, 125475, 125504, 125534, 125563, 125593, 125623, 125653, + 125682, 125712, 125741, 125771, 125800, 125829, 125858, 125888, + 125917, 125947, 125977, 126007, 126036, 126066, 126096, 126125, + 126155, 126184, 126213, 126243, 126272, 126301, 126331, 126361, + 126390, 126420, 126450, 126479, 126509, 126538, 126568, 126597, + 126627, 126656, 126685, 126715, 126745, 126774, 126804, 126834, + 126863, 126893, 126922, 126952, 126981, 127011, 127040, 127070, + 127099, 127129, 127158, 127188, 127217, 127247, 127276, 127306, + 127336, 127365, 127395, 127424, 127454, 127483, 127513, 127542, + 127571, 127601, 127631, 127660, 127690, 127720, 127749, 127779, + 127808, 127838, 127867, 127897, 127926, 127955, 127985, 128014, + 128044, 128074, 128103, 128133, 128163, 128192, 128222, 128251, + 128281, 128310, 128339, 128369, 128398, 128428, 128457, 128487, + 128517, 128547, 128576, 128606, 128635, 128665, 128694, 128723, + 128752, 128782, 128811, 128841, 128871, 128901, 128930, 128960, + 128990, 129019, 129049, 129078, 129107, 129136, 129166, 129195, + 129225, 129255, 129284, 129314, 129344, 129374, 129403, 129433, + 129462, 129491, 129521, 129550, 129579, 129609, 129639, 129668, + 129698, 129728, 129757, 129787, 129816, 129846, 129875, 129905, + 129934, 129963, 129993, 130022, 130052, 130082, 130111, 130141, + 130171, 130200, 130230, 130259, 130289, 130318, 130348, 130377, + 130406, 130436, 130465, 130495, 130525, 130554, 130584, 130614, + 130643, 130673, 130702, 130732, 130761, 130790, 130820, 130849, + 130879, 130908, 130938, 130968, 130997, 131027, 131057, 131086, + 131116, 131145, 131175, 131204, 131233, 131263, 131292, 131322, + 131351, 131381, 131411, 131441, 131470, 131500, 131529, 131559, + 131588, 131617, 131647, 131676, 131705, 131735, 131765, 131794, + 131824, 131854, 131884, 131913, 131943, 131972, 132001, 132030, + 132060, 132089, 132119, 132149, 132178, 132208, 132238, 132268, + 132297, 132327, 132356, 132385, 132414, 132444, 132473, 132503, + 132532, 132562, 132592, 132622, 132651, 132681, 132710, 132740, + 132769, 132799, 132828, 132857, 132887, 132916, 132946, 132976, + 133005, 133035, 133065, 133094, 133124, 133153, 133183, 133212, + 133241, 133271, 133300, 133330, 133360, 133389, 133419, 133448, + 133478, 133508, 133537, 133567, 133596, 133625, 133655, 133684, + 133714, 133743, 133773, 133802, 133832, 133862, 133891, 133921, + 133951, 133980, 134010, 134039, 134068, 134098, 134127, 134157, + 134186, 134216, 134245, 134275, 134305, 134335, 134364, 134394, + 134423, 134452, 134482, 134511, 134541, 134570, 134600, 134629, + 134659, 134689, 134718, 134748, 134778, 134807, 134837, 134866, + 134895, 134924, 134954, 134983, 135013, 135043, 135072, 135102, + 135132, 135162, 135191, 135221, 135250, 135279, 135308, 135338, + 135367, 135397, 135426, 135456, 135486, 135516, 135545, 135575, + 135605, 135634, 135663, 135692, 135722, 135751, 135781, 135810, + 135840, 135870, 135900, 135929, 135959, 135988, 136018, 136047, + 136076, 136106, 136135, 136165, 136194, 136224, 136254, 136283, + 136313, 136343, 136372, 136402, 136431, 136461, 136490, 136519, + 136549, 136578, 136608, 136637, 136667, 136697, 136726, 136756, + 136785, 136815, 136845, 136874, 136903, 136933, 136962, 136992, + 137021, 137051, 137080, 137110, 137140, 137169, 137199, 137228, + 137258, 137288, 137317, 137346, 137376, 137405, 137435, 137464, + 137494, 137523, 137553, 137583, 137612, 137642, 137672, 137701, + 137730, 137760, 137789, 137819, 137848, 137877, 137907, 137937, + 137966, 137996, 138026, 138056, 138085, 138115, 138144, 138173, + 138202, 138232, 138261, 138291, 138320, 138350, 138380, 138410, + 138439, 138469, 138499, 138528, 138557, 138586, 138616, 138645, + 138675, 138704, 138734, 138764, 138794, 138823, 138853, 138882, + 138912, 138941, 138970, 139000, 139029, 139059, 139088, 139118, + 139148, 139177, 139207, 139237, 139266, 139296, 139325, 139354, + 139384, 139413, 139443, 139472, 139502, 139531, 139561, 139591, + 139620, 139650, 139680, 139709, 139738, 139768, 139797, 139827, + 139856, 139886, 139915, 139945, 139974, 140004, 140034, 140063, + 140093, 140122, 140152, 140181, 140211, 140240, 140270, 140299, + 140329, 140358, 140388, 140417, 140447, 140477, 140506, 140536, + 140565, 140595, 140624, 140654, 140683, 140713, 140742, 140771, + 140801, 140831, 140860, 140890, 140920, 140949, 140979, 141008, + 141038, 141067, 141096, 141126, 141155, 141185, 141214, 141244, + 141274, 141304, 141333, 141363, 141392, 141421, 141451, 141480, + 141510, 141539, 141569, 141598, 141628, 141658, 141688, 141717, + 141747, 141776, 141806, 141835, 141864, 141894, 141923, 141953, + 141982, 142012, 142042, 142071, 142101, 142131, 142160, 142190, + 142219, 142248, 142278, 142307, 142337, 142366, 142396, 142425, + 142455, 142485, 142515, 142544, 142574, 142603, 142632, 142662, + 142691, 142721, 142750, 142780, 142809, 142839, 142869, 142898, + 142928, 142957, 142987, 143016, 143046, 143075, 143105, 143134, + 143164, 143193, 143223, 143252, 143282, 143312, 143341, 143371, + 143400, 143430, 143459, 143489, 143518, 143548, 143577, 143607, + 143636, 143666, 143695, 143725, 143755, 143784, 143814, 143843, + 143873, 143902, 143932, 143961, 143991, 144020, 144049, 144079, + 144109, 144138, 144168, 144198, 144227, 144257, 144286, 144316, + 144345, 144374, 144404, 144433, 144463, 144492, 144522, 144552, + 144582, 144611, 144641, 144670, 144700, 144729, 144758, 144788, + 144817, 144847, 144876, 144906, 144935, 144965, 144995, 145025, + 145054, 145084, 145113, 145143, 145172, 145201, 145230, 145260, + 145290, 145319, 145349, 145379, 145409, 145438, 145468, 145497, + 145526, 145556, 145585, 145615, 145644, 145674, 145703, 145733, + 145763, 145792, 145822, 145852, 145881, 145910, 145940, 145969, + 145999, 146028, 146058, 146087, 146117, 146146, 146176, 146206, + 146235, 146265, 146294, 146324, 146353, 146383, 146412, 146442, + 146471, 146501, 146530, 146560, 146589, 146619, 146649, 146678, + 146708, 146737, 146767, 146796, 146826, 146855, 146885, 146914, + 146943, 146973, 147003, 147032, 147062, 147092, 147121, 147151, + 147180, 147210, 147239, 147268, 147298, 147327, 147357, 147386, + 147416, 147446, 147476, 147505, 147535, 147564, 147594, 147623, + 147652, 147682, 147711, 147741, 147770, 147800, 147829, 147859, + 147889, 147919, 147948, 147978, 148007, 148036, 148066, 148095, + 148124, 148154, 148184, 148213, 148243, 148273, 148303, 148332, + 148362, 148391, 148421, 148450, 148479, 148508, 148538, 148567, + 148597, 148627, 148657, 148686, 148716, 148746, 148775, 148804, + 148834, 148863, 148892, 148922, 148951, 148981, 149011, 149040, + 149070, 149100, 149129, 149159, 149188, 149218, 149247, 149277, + 149306, 149335, 149365, 149395, 149424, 149454, 149484, 149513, + 149543, 149572, 149602, 149631, 149661, 149690, 149720, 149749, + 149778, 149808, 149838, 149867, 149897, 149926, 149956, 149986, + 150015, 150045, 150074, 150104, 150133, 150162, 150192, 150221, + 150251, 150280, 150310, 150340, 150370, 150399, 150429, 150458, + 150488, 150517, 150546, 150576, 150605, 150635, 150664, 150694, + 150724, 150753, 150783, 150813, 150842, 150872, 150901, 150930, + 150960, 150989, 151018, 151048, 151078, 151107, 151137, 151167, + 151197, 151226, 151256, 151285, 151315, 151344, 151373, 151402, + 151432, 151461, 151491, 151521, 151551, 151580, 151610, 151640, + 151669, 151699, 151728, 151757, 151786, 151816, 151845, 151875, + 151905, 151934, 151964, 151994, 152024, 152053, 152082, 152112, + 152141, 152170, 152200, 152229, 152259, 152289, 152318, 152348, + 152378, 152407, 152437, 152466, 152496, 152525, 152555, 152584, + 152613, 152643, 152672, 152702, 152732, 152761, 152791, 152821, + 152850, 152880, 152909, 152939, 152968, 152997, 153027, 153056, + 153086, 153115, 153145, 153175, 153204, 153234, 153264, 153293, + 153323, 153352, 153382, 153411, 153440, 153470, 153499, 153529, + 153558, 153588, 153618, 153647, 153677, 153707, 153736, 153766, + 153795, 153824, 153854, 153883, 153913, 153942, 153972, 154001, + 154031, 154061, 154091, 154120, 154150, 154179, 154209, 154238, + 154267, 154296, 154326, 154355, 154385, 154415, 154445, 154474, + 154504, 154534, 154563, 154593, 154622, 154651, 154680, 154710, + 154739, 154769, 154799, 154828, 154858, 154888, 154918, 154947, + 154976, 155006, 155035, 155064, 155094, 155123, 155153, 155182, + 155212, 155242, 155272, 155301, 155331, 155360, 155390, 155419, + 155448, 155478, 155507, 155537, 155566, 155596, 155626, 155655, + 155685, 155715, 155744, 155774, 155803, 155833, 155862, 155891, + 155921, 155950, 155980, 156009, 156039, 156069, 156098, 156128, + 156158, 156187, 156217, 156246, 156275, 156305, 156334, 156364, + 156393, 156423, 156452, 156482, 156512, 156541, 156571, 156601, + 156630, 156660, 156689, 156718, 156748, 156777, 156807, 156836, + 156866, 156895, 156925, 156955, 156985, 157014, 157044, 157073, + 157102, 157132, 157161, 157190, 157220, 157249, 157279, 157309, + 157339, 157368, 157398, 157428, 157457, 157487, 157516, 157545, + 157574, 157604, 157633, 157663, 157693, 157722, 157752, 157782, + 157812, 157841, 157871, 157900, 157929, 157958, 157988, 158017, + 158047, 158076, 158106, 158136, 158166, 158195, 158225, 158254, + 158284, 158313, 158342, 158372, 158401, 158431, 158460, 158490, + 158520, 158550, 158579, 158609, 158638, 158668, 158697, 158726, + 158756, 158785, 158815, 158844, 158874, 158904, 158933, 158963, + 158993, 159022, 159052, 159081, 159110, 159140, 159169, 159199, + 159228, 159258, 159287, 159317, 159347, 159376, 159406, 159435, + 159465, 159494, 159524, 159553, 159583, 159612, 159642, 159671, + 159701, 159730, 159760, 159790, 159819, 159849, 159878, 159908, + 159937, 159967, 159996, 160026, 160055, 160085, 160114, 160144, + 160173, 160203, 160233, 160262, 160292, 160322, 160351, 160380, + 160410, 160439, 160468, 160498, 160527, 160557, 160587, 160616, + 160646, 160676, 160706, 160735, 160764, 160794, 160823, 160852, + 160882, 160911, 160941, 160970, 161000, 161030, 161060, 161089, + 161119, 161148, 161178, 161207, 161236, 161266, 161295, 161325, + 161354, 161384, 161414, 161444, 161473, 161503, 161532, 161562, + 161591, 161620, 161650, 161679, 161709, 161738, 161768, 161798, + 161827, 161857, 161887, 161916, 161946, 161975, 162004, 162034, + 162063, 162093, 162122, 162152, 162181, 162211, 162241, 162270, + 162300, 162330, 162359, 162388, 162418, 162447, 162477, 162506, + 162536, 162565, 162595, 162624, 162654, 162684, 162713, 162743, + 162772, 162802, 162831, 162861, 162890, 162920, 162949, 162979, + 163008, 163038, 163067, 163097, 163127, 163156, 163186, 163215, + 163245, 163274, 163304, 163333, 163363, 163392, 163421, 163451, + 163481, 163510, 163540, 163570, 163599, 163629, 163658, 163688, + 163717, 163746, 163776, 163805, 163835, 163864, 163894, 163924, + 163954, 163983, 164013, 164042, 164072, 164101, 164130, 164160, + 164189, 164219, 164248, 164278, 164308, 164338, 164367, 164397, + 164426, 164456, 164485, 164514, 164544, 164573, 164603, 164632, + 164662, 164692, 164721, 164751, 164781, 164810, 164840, 164869, + 164898, 164928, 164957, 164987, 165016, 165046, 165075, 165105, + 165135, 165165, 165194, 165224, 165253, 165282, 165312, 165341, + 165371, 165400, 165430, 165459, 165489, 165519, 165548, 165578, + 165607, 165637, 165666, 165696, 165725, 165755, 165784, 165814, + 165843, 165873, 165902, 165932, 165962, 165991, 166021, 166050, + 166080, 166109, 166139, 166168, 166198, 166227, 166257, 166286, + 166316, 166345, 166375, 166404, 166434, 166464, 166493, 166523, + 166552, 166582, 166611, 166640, 166670, 166699, 166729, 166758, + 166788, 166818, 166848, 166877, 166907, 166936, 166966, 166995, + 167024, 167054, 167083, 167113, 167142, 167172, 167202, 167232, + 167261, 167291, 167320, 167350, 167379, 167408, 167438, 167467, + 167497, 167526, 167556, 167585, 167615, 167645, 167675, 167704, + 167734, 167763, 167792, 167822, 167851, 167880, 167910, 167940, + 167969, 167999, 168029, 168059, 168088, 168118, 168147, 168176, + 168206, 168235, 168264, 168294, 168323, 168353, 168383, 168413, + 168442, 168472, 168502, 168531, 168560, 168590, 168619, 168649, + 168678, 168707, 168737, 168767, 168796, 168826, 168856, 168885, + 168915, 168944, 168974, 169003, 169033, 169062, 169092, 169121, + 169151, 169180, 169210, 169239, 169269, 169299, 169328, 169358, + 169387, 169417, 169446, 169476, 169505, 169534, 169564, 169593, + 169623, 169653, 169682, 169712, 169742, 169771, 169801, 169830, + 169860, 169889, 169918, 169948, 169977, 170007, 170036, 170066, + 170096, 170126, 170155, 170185, 170214, 170244, 170273, 170302, + 170332, 170361, 170391, 170420, 170450, 170479, 170509, 170539, + 170569, 170598, 170628, 170657, 170686, 170716, 170745, 170774, + 170804, 170834, 170863, 170893, 170923, 170953, 170982, 171012, + 171041, 171070, 171100, 171129, 171158, 171188, 171217, 171247, + 171277, 171307, 171336, 171366, 171396, 171425, 171454, 171484, + 171513, 171542, 171572, 171601, 171631, 171661, 171690, 171720, + 171750, 171779, 171809, 171838, 171868, 171897, 171927, 171956, + 171985, 172015, 172045, 172074, 172104, 172133, 172163, 172193, + 172222, 172252, 172281, 172311, 172340, 172369, 172399, 172428, + 172458, 172488, 172517, 172547, 172576, 172606, 172636, 172665, + 172695, 172724, 172754, 172783, 172812, 172842, 172871, 172901, + 172930, 172960, 172990, 173019, 173049, 173079, 173108, 173138, + 173167, 173196, 173226, 173255, 173285, 173314, 173344, 173374, + 173403, 173433, 173463, 173492, 173522, 173551, 173580, 173610, + 173639, 173668, 173698, 173728, 173757, 173787, 173817, 173847, + 173876, 173906, 173935, 173964, 173994, 174023, 174052, 174082, + 174111, 174141, 174171, 174201, 174230, 174260, 174290, 174319, + 174348, 174378, 174407, 174436, 174466, 174495, 174525, 174555, + 174584, 174614, 174644, 174674, 174703, 174732, 174762, 174791, + 174820, 174850, 174879, 174909, 174938, 174968, 174998, 175028, + 175057, 175087, 175116, 175146, 175175, 175204, 175234, 175263, + 175293, 175322, 175352, 175382, 175411, 175441, 175471, 175500, + 175530, 175559, 175589, 175618, 175647, 175677, 175706, 175736, + 175765, 175795, 175825, 175854, 175884, 175913, 175943, 175973, + 176002, 176032, 176061, 176090, 176120, 176149, 176179, 176208, + 176238, 176268, 176297, 176327, 176357, 176386, 176416, 176445, + 176474, 176504, 176533, 176563, 176592, 176622, 176651, 176681, + 176711, 176741, 176770, 176800, 176829, 176858, 176888, 176917, + 176946, 176976, 177005, 177035, 177065, 177095, 177124, 177154, + 177184, 177213, 177242, 177272, 177301, 177330, 177360, 177389, + 177419, 177449, 177478, 177508, 177538, 177568, 177597, 177626, + 177656, 177685, 177714, 177744, 177773, 177803, 177832, 177862, + 177892, 177922, 177951, 177981, 178010, 178040, 178069, 178098, + 178128, 178157, 178187, 178216, 178246, 178276, 178305, 178335, + 178365, 178394, 178424, 178453, 178482, 178512, 178541, 178571, + 178600, 178630, 178659, 178689, 178719, 178748, 178778, 178808, + 178837, 178867, 178896, 178925, 178955, 178984, 179014, 179043, + 179073, 179102, 179132, 179162, 179191, 179221, 179251, 179280, + 179310, 179339, 179368, 179398, 179427, 179457, 179486, 179516, + 179545, 179575, 179605, 179634, 179664, 179694, 179723, 179752, + 179782, 179811, 179840, 179870, 179899, 179929, 179959, 179989, + 180018, 180048, 180078, 180107, 180136, 180166, 180195, 180224, + 180254, 180283, 180313, 180343, 180372, 180402, 180432, 180462, + 180491, 180520, 180550, 180579, 180608, 180638, 180667, 180697, + 180726, 180756, 180786, 180816, 180845, 180875, 180904, 180934, + 180963, 180992, 181022, 181051, 181081, 181110, 181140, 181170, + 181200, 181229, 181259, 181288, 181318, 181347, 181376, 181406, + 181435, 181465, 181494, 181524, 181554, 181583, 181613, 181643, + 181672, 181702, 181731, 181760, 181790, 181819, 181849, 181878, + 181908, 181937, 181967, 181997, 182026, 182056, 182085, 182115, + 182144, 182174, 182203, 182233, 182262, 182292, 182321, 182351, + 182380, 182410, 182440, 182469, 182499, 182528, 182558, 182587, + 182617, 182646, 182676, 182705, 182735, 182764, 182794, 182823, + 182853, 182883, 182912, 182942, 182972, 183001, 183030, 183060, + 183089, 183118, 183148, 183177, 183207, 183237, 183266, 183296, + 183326, 183356, 183385, 183414, 183444, 183473, 183502, 183532, + 183561, 183591, 183620, 183650, 183680, 183710, 183739, 183769, + 183798, 183828, 183857, 183886, 183916, 183945, 183975, 184004, + 184034, 184064, 184094, 184123, 184153, 184182, 184212, 184241, + 184270, 184300, 184329, 184359, 184388, 184418, 184447, 184477, + 184507, 184537, 184566, 184596, 184625, 184654, 184684, 184713, + 184743, 184772, 184802, 184831, 184861, 184891, 184920, 184950, + 184979, 185009, 185038, 185068, 185097, 185127, 185156, 185186, + 185215, 185245, 185274, 185304, 185334, 185363, 185393, 185422, + 185452, 185481, 185511, 185540, 185570, 185599, 185629, 185658, + 185688, 185717, 185747, 185777, 185806, 185836, 185865, 185895, + 185924, 185954, 185983, 186012, 186042, 186071, 186101, 186131, + 186160, 186190, 186220, 186249, 186279, 186308, 186338, 186367, + 186396, 186426, 186455, 186485, 186514, 186544, 186574, 186604, + 186633, 186663, 186692, 186722, 186751, 186780, 186810, 186839, + 186869, 186898, 186928, 186958, 186988, 187017, 187047, 187076, + 187106, 187135, 187164, 187194, 187223, 187252, 187282, 187312, + 187341, 187371, 187401, 187431, 187460, 187490, 187519, 187548, + 187578, 187607, 187636, 187666, 187696, 187725, 187755, 187785, + 187814, 187844, 187874, 187903, 187932, 187962, 187991, 188021, + 188050, 188080, 188109, 188139, 188169, 188198, 188228, 188257, + 188287, 188316, 188346, 188375, 188405, 188434, 188464, 188493, + 188523, 188552, 188582, 188611, 188641, 188671, 188700, 188730, + 188759, 188789, 188818, 188848, 188877, 188906, 188936, 188966, + 188995, 189025, 189054, 189084, 189114, 189143, 189173, 189202, + 189232, 189261, 189290, 189320, 189349, 189379, 189408, 189438, + 189468, 189498, 189527, 189557, 189586, 189616, 189645, 189674, + 189704, 189733, 189763, 189792, 189822, 189852, 189882, 189911, + 189941, 189970, 190000, 190029, 190058, 190088, 190117, 190146, + 190176, 190206, 190235, 190265, 190295, 190325, 190354, 190384, + 190413, 190442, 190472, 190501, 190530, 190560, 190590, 190619, + 190649, 190679, 190709, 190738, 190768, 190797, 190826, 190856, + 190885, 190914, 190944, 190973, 191003, 191033, 191063, 191092, + 191122, 191152, 191181, 191210, 191240, 191269, 191299, 191328, + 191357, 191387, 191417, 191446, 191476, 191506, 191535, 191565, + 191594, 191624, 191653, 191683, 191712, 191742, 191771, 191801, + 191830, 191860, 191889, 191919, 191949, 191978, 192008, 192037, + 192067, 192096, 192126, 192155, 192184, 192214, 192243, 192273, + 192303, 192332, 192362, 192392, 192421, 192451, 192480, 192510, + 192539, 192568, 192598, 192627, 192657, 192686, 192716, 192746, + 192776, 192805, 192835, 192864, 192894, 192923, 192952, 192982, + 193011, 193041, 193070, 193100, 193130, 193159, 193189, 193219, + 193248, 193278, 193307, 193336, 193366, 193395, 193424, 193454, + 193484, 193513, 193543, 193573, 193603, 193632, 193662, 193691, + 193720, 193750, 193779, 193808, 193838, 193867, 193897, 193927, + 193957, 193986, 194016, 194046, 194075, 194104, 194134, 194163, + 194192, 194222, 194251, 194281, 194311, 194340, 194370, 194400, + 194429, 194459, 194488, 194518, 194547, 194577, 194606, 194635, + 194665, 194695, 194724, 194754, 194783, 194813, 194843, 194872, + 194902, 194931, 194961, 194990, 195019, 195049, 195078, 195108, + 195138, 195167, 195197, 195226, 195256, 195286, 195315, 195345, + 195374, 195404, 195433, 195462, 195492, 195521, 195551, 195580, + 195610, 195640, 195669, 195699, 195729, 195758, 195788, 195817, + 195846, 195876, 195905, 195935, 195964, 195994, 196024, 196053, + 196083, 196113, 196142, 196172, 196201, 196230, 196260, 196289, + 196318, 196348, 196378, 196407, 196437, 196467, 196497, 196526, + 196556, 196585, 196614, 196644, 196673, 196702, 196732, 196761, + 196791, 196821, 196851, 196880, 196910, 196940, 196969, 196998, + 197028, 197057, 197086, 197116, 197145, 197175, 197205, 197234, + 197264, 197294, 197324, 197353, 197382, 197412, 197441, 197470, + 197500, 197529, 197559, 197588, 197618, 197648, 197678, 197707, + 197737, 197766, 197796, 197825, 197854, 197884, 197913, 197943, + 197972, 198002, 198032, 198061, 198091, 198121, 198150, 198180, + 198209, 198239, 198268, 198297, 198327, 198356, 198386, 198415, + 198445, 198475, 198504, 198534, 198564, 198593, 198623, 198652, + 198682, 198711, 198740, 198770, 198799, 198829, 198858, 198888, + 198918, 198947, 198977, 199007, 199036, 199066, 199095, 199124, + 199154, 199183, 199213, 199242, 199272, 199301, 199331, 199361, + 199391, 199420, 199450, 199479, 199508, 199538, 199567, 199596, + 199626, 199655, 199685, 199715, 199745, 199774, 199804, 199834, + 199863, 199892, 199922, 199951, 199980, 200010, 200039, 200069, + 200099, 200128, 200158, 200188, 200218, 200247, 200276, 200306, + 200335, 200364, 200394, 200423, 200453, 200482, 200512, 200542, + 200572, 200601, 200631, 200660, 200690, 200719, 200748, 200778, + 200807, 200837, 200866, 200896, 200926, 200955, 200985, 201015, + 201044, 201074, 201103, 201132, 201162, 201191, 201221, 201250, + 201280, 201309, 201339, 201369, 201398, 201428, 201458, 201487, + 201517, 201546, 201575, 201605, 201634, 201664, 201693, 201723, + 201752, 201782, 201812, 201841, 201871, 201901, 201930, 201960, + 201989, 202018, 202048, 202077, 202107, 202136, 202166, 202195, + 202225, 202255, 202284, 202314, 202344, 202373, 202402, 202432, + 202461, 202490, 202520, 202549, 202579, 202609, 202639, 202668, + 202698, 202728, 202757, 202786, 202816, 202845, 202874, 202904, + 202933, 202963, 202993, 203022, 203052, 203082, 203112, 203141, + 203170, 203200, 203229, 203258, 203288, 203317, 203347, 203376, + 203406, 203436, 203466, 203495, 203525, 203554, 203584, 203613, + 203642, 203672, 203701, 203731, 203760, 203790, 203820, 203850, + 203879, 203909, 203938, 203968, 203997, 204026, 204056, 204085, + 204115, 204144, 204174, 204204, 204233, 204263, 204293, 204322, + 204352, 204381, 204410, 204440, 204469, 204499, 204528, 204558, + 204587, 204617, 204647, 204676, 204706, 204735, 204765, 204794, + 204824, 204853, 204883, 204912, 204942, 204971, 205001, 205030, + 205060, 205090, 205119, 205149, 205178, 205208, 205237, 205267, + 205296, 205326, 205355, 205384, 205414, 205444, 205473, 205503, + 205533, 205562, 205592, 205622, 205651, 205680, 205710, 205739, + 205768, 205798, 205827, 205857, 205887, 205916, 205946, 205976, + 206006, 206035, 206064, 206094, 206123, 206152, 206182, 206211, + 206241, 206270, 206300, 206330, 206360, 206389, 206419, 206448, + 206478, 206507, 206536, 206566, 206595, 206625, 206654, 206684, + 206714, 206744, 206773, 206803, 206832, 206862, 206891, 206920, + 206950, 206979, 207009, 207038, 207068, 207098, 207127, 207157, + 207187, 207216, 207246, 207275, 207304, 207334, 207363, 207393, + 207422, 207452, 207481, 207511, 207541, 207570, 207600, 207629, + 207659, 207688, 207718, 207747, 207777, 207806, 207836, 207865, + 207895, 207924, 207954, 207984, 208013, 208043, 208072, 208102, + 208131, 208161, 208190, 208220, 208249, 208279, 208308, 208338, + 208367, 208397, 208427, 208456, 208486, 208515, 208545, 208574, + 208604, 208633, 208662, 208692, 208721, 208751, 208781, 208810, + 208840, 208870, 208899, 208929, 208958, 208988, 209017, 209046, + 209076, 209105, 209135, 209164, 209194, 209224, 209254, 209283, + 209313, 209342, 209372, 209401, 209430, 209460, 209489, 209519, + 209548, 209578, 209608, 209638, 209667, 209697, 209726, 209756, + 209785, 209814, 209844, 209873, 209902, 209932, 209962, 209992, + 210021, 210051, 210081, 210110, 210140, 210169, 210198, 210228, + 210257, 210286, 210316, 210346, 210375, 210405, 210435, 210464, + 210494, 210524, 210553, 210582, 210612, 210641, 210671, 210700, + 210730, 210759, 210789, 210819, 210848, 210878, 210907, 210937, + 210966, 210996, 211025, 211055, 211084, 211114, 211143, 211173, + 211202, 211232, 211261, 211291, 211321, 211350, 211380, 211409, + 211439, 211468, 211498, 211527, 211556, 211586, 211616, 211645, + 211675, 211704, 211734, 211764, 211793, 211823, 211852, 211882, + 211911, 211940, 211970, 211999, 212029, 212058, 212088, 212118, + 212148, 212177, 212207, 212236, 212266, 212295, 212324, 212354, + 212383, 212413, 212442, 212472, 212502, 212532, 212561, 212591, + 212620, 212650, 212679, 212708, 212738, 212767, 212796, 212826, + 212856, 212886, 212915, 212945, 212975, 213004, 213034, 213063, + 213092, 213122, 213151, 213180, 213210, 213240, 213269, 213299, + 213329, 213359, 213388, 213418, 213447, 213476, 213506, 213535, + 213564, 213594, 213623, 213653, 213683, 213713, 213742, 213772, + 213801, 213831, 213860, 213890, 213919, 213949, 213978, 214007, + 214037, 214067, 214096, 214126, 214156, 214185, 214215, 214244, + 214274, 214303, 214333, 214362, 214391, 214421, 214451, 214480, + 214510, 214539, 214569, 214599, 214628, 214658, 214687, 214717, + 214746, 214776, 214805, 214834, 214864, 214893, 214923, 214953, + 214982, 215012, 215042, 215071, 215101, 215130, 215160, 215189, + 215218, 215248, 215277, 215307, 215336, 215366, 215396, 215425, + 215455, 215485, 215514, 215544, 215573, 215602, 215632, 215661, + 215690, 215720, 215750, 215779, 215809, 215839, 215869, 215898, + 215928, 215957, 215986, 216016, 216045, 216074, 216104, 216134, + 216163, 216193, 216223, 216253, 216282, 216312, 216341, 216370, + 216400, 216429, 216458, 216488, 216517, 216547, 216577, 216607, + 216636, 216666, 216696, 216725, 216754, 216784, 216813, 216842, + 216872, 216901, 216931, 216961, 216990, 217020, 217050, 217079, + 217109, 217138, 217168, 217197, 217226, 217256, 217285, 217315, + 217344, 217374, 217404, 217433, 217463, 217493, 217522, 217552, + 217581, 217611, 217640, 217669, 217699, 217728, 217758, 217788, + 217817, 217847, 217876, 217906, 217936, 217965, 217995, 218024, + 218054, 218083, 218112, 218142, 218171, 218201, 218230, 218260, + 218290, 218319, 218349, 218379, 218408, 218438, 218467, 218496, + 218526, 218555, 218585, 218614, 218644, 218674, 218703, 218733, + 218763, 218792, 218822, 218851, 218880, 218910, 218939, 218968, + 218998, 219028, 219057, 219087, 219117, 219147, 219176, 219206, + 219235, 219264, 219294, 219323, 219352, 219382, 219411, 219441, + 219471, 219501, 219530, 219560, 219590, 219619, 219648, 219678, + 219707, 219736, 219766, 219795, 219825, 219855, 219884, 219914, + 219944, 219973, 220003, 220032, 220062, 220091, 220120, 220150, + 220179, 220209, 220238, 220268, 220298, 220328, 220357, 220387, + 220416, 220446, 220475, 220504, 220534, 220563, 220593, 220622, + 220652, 220682, 220711, 220741, 220771, 220800, 220830, 220859, + 220889, 220918, 220947, 220977, 221006, 221036, 221065, 221095, + 221125, 221154, 221184, 221213, 221243, 221273, 221302, 221332, + 221361, 221390, 221420, 221449, 221479, 221508, 221538, 221568, + 221597, 221627, 221657, 221686, 221716, 221745, 221774, 221804, + 221833, 221862, 221892, 221922, 221951, 221981, 222011, 222041, + 222070, 222100, 222129, 222158, 222188, 222217, 222246, 222276, + 222305, 222335, 222365, 222395, 222424, 222454, 222484, 222513, + 222542, 222572, 222601, 222630, 222660, 222689, 222719, 222749, + 222778, 222808, 222838, 222868, 222897, 222926, 222956, 222985, + 223014, 223044, 223073, 223103, 223132, 223162, 223192, 223222, + 223251, 223281, 223310, 223340, 223369, 223398, 223428, 223457, + 223487, 223516, 223546, 223576, 223605, 223635, 223665, 223694, + 223724, 223753, 223782, 223812, 223841, 223871, 223900, 223930, + 223959, 223989, 224019, 224048, 224078, 224107, 224137, 224166, + 224196, 224225, 224255, 224284, 224314, 224343, 224373, 224402, + 224432, 224462, 224491, 224521, 224551, 224580, 224609, 224639, + 224668, 224698, 224727, 224757, 224786, 224816, 224845, 224875, + 224905, 224934, 224964, 224994, 225023, 225052, 225082, 225111, + 225140, 225170, 225199, 225229, 225259, 225289, 225318, 225348, + 225378, 225407, 225436, 225466, 225495, 225524, 225554, 225583, + 225613, 225643, 225672, 225702, 225732, 225762, 225791, 225820, + 225850, 225879, 225908, 225938, 225967, 225997, 226026, 226056, + 226086, 226116, 226145, 226175, 226204, 226234, 226263, 226292, + 226322, 226351, 226381, 226410, 226440, 226470, 226499, 226529, + 226559, 226588, 226618, 226647, 226676, 226706, 226735, 226765, + 226794, 226824, 226853, 226883, 226913, 226943, 226972, 227002, + 227031, 227060, 227090, 227119, 227149, 227178, 227208, 227237, + 227267, 227297, 227326, 227356, 227385, 227415, 227444, 227474, + 227503, 227533, 227562, 227592, 227621, 227651, 227680, 227710, + 227739, 227769, 227799, 227828, 227858, 227887, 227917, 227946, + 227976, 228005, 228034, 228064, 228093, 228123, 228153, 228183, + 228212, 228242, 228271, 228301, 228330, 228360, 228389, 228418, + 228448, 228477, 228507, 228537, 228566, 228596, 228626, 228655, + 228685, 228714, 228744, 228773, 228802, 228832, 228861, 228891, + 228920, 228950, 228980, 229010, 229039, 229069, 229098, 229128, + 229157, 229186, 229216, 229245, 229275, 229304, 229334, 229364, + 229394, 229423, 229453, 229482, 229512, 229541, 229570, 229600, + 229629, 229659, 229688, 229718, 229748, 229777, 229807, 229837, + 229866, 229896, 229925, 229954, 229984, 230013, 230043, 230072, + 230102, 230131, 230161, 230191, 230220, 230250, 230279, 230309, + 230338, 230368, 230397, 230427, 230456, 230486, 230515, 230545, + 230574, 230604, 230634, 230663, 230693, 230722, 230752, 230781, + 230811, 230840, 230870, 230899, 230929, 230958, 230988, 231017, + 231047, 231077, 231106, 231136, 231165, 231195, 231224, 231254, + 231283, 231312, 231342, 231371, 231401, 231431, 231460, 231490, + 231520, 231549, 231579, 231608, 231638, 231667, 231696, 231726, + 231755, 231785, 231814, 231844, 231874, 231904, 231933, 231963, + 231992, 232022, 232051, 232080, 232110, 232139, 232169, 232198, + 232228, 232258, 232288, 232317, 232347, 232376, 232406, 232435, + 232464, 232494, 232523, 232552, 232582, 232612, 232642, 232671, + 232701, 232731, 232760, 232790, 232819, 232848, 232878, 232907, + 232936, 232966, 232996, 233025, 233055, 233085, 233114, 233144, + 233174, 233203, 233232, 233262, 233291, 233320, 233350, 233380, + 233409, 233439, 233468, 233498, 233528, 233557, 233587, 233616, + 233646, 233675, 233705, 233734, 233764, 233793, 233823, 233852, + 233882, 233911, 233941, 233971, 234000, 234030, 234059, 234089, + 234118, 234148, 234177, 234206, 234236, 234265, 234295, 234325, + 234354, 234384, 234414, 234443, 234473, 234502, 234532, 234561, + 234590, 234620, 234649, 234679, 234708, 234738, 234768, 234798, + 234827, 234857, 234886, 234916, 234945, 234974, 235004, 235033, + 235063, 235092, 235122, 235152, 235182, 235211, 235241, 235270, + 235300, 235329, 235358, 235388, 235417, 235446, 235476, 235506, + 235535, 235565, 235595, 235625, 235654, 235684, 235713, 235742, + 235772, 235801, 235830, 235860, 235890, 235919, 235949, 235979, + 236009, 236038, 236068, 236097, 236126, 236156, 236185, 236214, + 236244, 236273, 236303, 236333, 236363, 236392, 236422, 236451, + 236481, 236510, 236540, 236569, 236598, 236628, 236657, 236687, + 236717, 236746, 236776, 236806, 236835, 236865, 236894, 236924, + 236953, 236983, 237012, 237041, 237071, 237100, 237130, 237160, + 237189, 237219, 237249, 237278, 237308, 237337, 237367, 237396, + 237426, 237455, 237484, 237514, 237543, 237573, 237603, 237632, + 237662, 237692, 237721, 237751, 237780, 237810, 237839, 237868, + 237898, 237927, 237957, 237986, 238016, 238046, 238075, 238105, + 238135, 238164, 238194, 238223, 238252, 238282, 238311, 238340, + 238370, 238400, 238429, 238459, 238489, 238519, 238548, 238578, + 238607, 238636, 238666, 238695, 238724, 238754, 238783, 238813, + 238843, 238873, 238903, 238932, 238962, 238991, 239020, 239050, + 239079, 239108, 239138, 239167, 239197, 239227, 239257, 239286, + 239316, 239346, 239375, 239404, 239434, 239463, 239492, 239522, + 239551, 239581, 239611, 239640, 239670, 239700, 239729, 239759, + 239788, 239818, 239847, 239876, 239906, 239935, 239965, 239994, + 240024, 240054, 240083, 240113, 240143, 240172, 240202, 240231, + 240261, 240290, 240319, 240349, 240378, 240408, 240437, 240467, + 240497, 240526, 240556, 240586, 240615, 240645, 240674, 240704, + 240733, 240762, 240792, 240821, 240851, 240880, 240910, 240940, + 240969, 240999, 241029, 241029, +} + +var YearTable = []int{ + 0, 12, 25, 37, 49, 62, 74, 86, + 99, 111, 123, 136, 148, 161, 173, 185, + 198, 210, 222, 235, 247, 260, 272, 284, + 297, 309, 321, 334, 346, 358, 371, 383, + 396, 408, 420, 433, 445, 457, 470, 482, + 495, 507, 519, 532, 544, 556, 569, 581, + 593, 606, 618, 631, 643, 655, 668, 680, + 692, 705, 717, 729, 742, 754, 767, 779, + 791, 804, 816, 828, 841, 853, 866, 878, + 890, 903, 915, 927, 940, 952, 964, 977, + 989, 1002, 1014, 1026, 1039, 1051, 1063, 1076, + 1088, 1101, 1113, 1125, 1138, 1150, 1162, 1175, + 1187, 1199, 1212, 1224, 1237, 1249, 1261, 1274, + 1286, 1298, 1311, 1323, 1336, 1348, 1360, 1373, + 1385, 1397, 1410, 1422, 1434, 1447, 1459, 1472, + 1484, 1496, 1509, 1521, 1533, 1546, 1558, 1571, + 1583, 1595, 1608, 1620, 1632, 1645, 1657, 1670, + 1682, 1694, 1707, 1719, 1731, 1744, 1756, 1768, + 1781, 1793, 1806, 1818, 1830, 1843, 1855, 1867, + 1880, 1892, 1904, 1917, 1929, 1942, 1954, 1966, + 1979, 1991, 2003, 2016, 2028, 2041, 2053, 2065, + 2078, 2090, 2102, 2115, 2127, 2139, 2152, 2164, + 2177, 2189, 2201, 2214, 2226, 2238, 2251, 2263, + 2276, 2288, 2300, 2313, 2325, 2337, 2350, 2362, + 2374, 2387, 2399, 2412, 2424, 2436, 2449, 2461, + 2473, 2486, 2498, 2511, 2523, 2535, 2548, 2560, + 2572, 2585, 2597, 2609, 2622, 2634, 2647, 2659, + 2671, 2684, 2696, 2708, 2721, 2733, 2746, 2758, + 2770, 2783, 2795, 2807, 2820, 2832, 2844, 2857, + 2869, 2882, 2894, 2906, 2919, 2931, 2943, 2956, + 2968, 2981, 2993, 3005, 3018, 3030, 3042, 3055, + 3067, 3079, 3092, 3104, 3117, 3129, 3141, 3154, + 3166, 3178, 3191, 3203, 3216, 3228, 3240, 3253, + 3265, 3277, 3290, 3302, 3314, 3327, 3339, 3352, + 3364, 3376, 3389, 3401, 3413, 3426, 3438, 3450, + 3463, 3475, 3488, 3500, 3512, 3525, 3537, 3549, + 3562, 3574, 3587, 3599, 3611, 3624, 3636, 3648, + 3661, 3673, 3685, 3698, 3710, 3723, 3735, 3747, + 3760, 3772, 3784, 3797, 3809, 3822, 3834, 3846, + 3859, 3871, 3883, 3896, 3908, 3920, 3933, 3945, + 3958, 3970, 3982, 3995, 4007, 4019, 4032, 4044, + 4057, 4069, 4081, 4094, 4106, 4118, 4131, 4143, + 4155, 4168, 4180, 4193, 4205, 4217, 4230, 4242, + 4254, 4267, 4279, 4292, 4304, 4316, 4329, 4341, + 4353, 4366, 4378, 4390, 4403, 4415, 4428, 4440, + 4452, 4465, 4477, 4489, 4502, 4514, 4527, 4539, + 4551, 4564, 4576, 4588, 4601, 4613, 4625, 4638, + 4650, 4663, 4675, 4687, 4700, 4712, 4724, 4737, + 4749, 4762, 4774, 4786, 4799, 4811, 4823, 4836, + 4848, 4860, 4873, 4885, 4898, 4910, 4922, 4935, + 4947, 4959, 4972, 4984, 4996, 5009, 5021, 5034, + 5046, 5058, 5071, 5083, 5095, 5108, 5120, 5133, + 5145, 5157, 5170, 5182, 5194, 5207, 5219, 5231, + 5244, 5256, 5269, 5281, 5293, 5306, 5318, 5330, + 5343, 5355, 5368, 5380, 5392, 5405, 5417, 5429, + 5442, 5454, 5467, 5479, 5491, 5504, 5516, 5528, + 5541, 5553, 5565, 5578, 5590, 5603, 5615, 5627, + 5640, 5652, 5664, 5677, 5689, 5702, 5714, 5726, + 5739, 5751, 5763, 5776, 5788, 5800, 5813, 5825, + 5838, 5850, 5862, 5875, 5887, 5899, 5912, 5924, + 5937, 5949, 5961, 5974, 5986, 5998, 6011, 6023, + 6035, 6048, 6060, 6073, 6085, 6097, 6110, 6122, + 6134, 6147, 6159, 6171, 6184, 6196, 6209, 6221, + 6233, 6246, 6258, 6270, 6283, 6295, 6308, 6320, + 6332, 6345, 6357, 6369, 6382, 6394, 6406, 6419, + 6431, 6444, 6456, 6468, 6481, 6493, 6505, 6518, + 6530, 6543, 6555, 6567, 6580, 6592, 6604, 6617, + 6629, 6641, 6654, 6666, 6679, 6691, 6703, 6716, + 6728, 6740, 6753, 6765, 6778, 6790, 6802, 6815, + 6827, 6839, 6852, 6864, 6876, 6889, 6901, 6914, + 6926, 6938, 6951, 6963, 6975, 6988, 7000, 7013, + 7025, 7037, 7050, 7062, 7074, 7087, 7099, 7111, + 7124, 7136, 7149, 7161, 7173, 7186, 7198, 7210, + 7223, 7235, 7248, 7260, 7272, 7285, 7297, 7309, + 7322, 7334, 7347, 7359, 7371, 7384, 7396, 7408, + 7421, 7433, 7445, 7458, 7470, 7483, 7495, 7507, + 7520, 7532, 7544, 7557, 7569, 7581, 7594, 7606, + 7619, 7631, 7643, 7656, 7668, 7680, 7693, 7705, + 7718, 7730, 7742, 7755, 7767, 7779, 7792, 7804, + 7816, 7829, 7841, 7854, 7866, 7878, 7891, 7903, + 7915, 7928, 7940, 7953, 7965, 7977, 7990, 8002, + 8014, 8027, 8039, 8051, 8064, 8076, 8089, 8101, + 8113, 8126, 8138, 8150, 8163, +} + +var LeapTable = []int{ + 0, 13, 0, 0, 10, 0, 0, 6, + 0, 0, 4, 0, 12, 0, 0, 8, + 0, 0, 5, 0, 13, 0, 0, 10, + 0, 0, 6, 0, 0, 2, 0, 13, + 0, 0, 8, 0, 0, 5, 0, 13, + 0, 0, 9, 0, 0, 7, 0, 0, + 3, 0, 12, 0, 0, 8, 0, 0, + 5, 0, 0, 2, 0, 10, 0, 0, + 7, 0, 0, 3, 0, 12, 0, 0, + 8, 0, 0, 4, 0, 0, 3, 0, + 10, 0, 0, 7, 0, 0, 3, 0, + 11, 0, 0, 9, 0, 0, 5, 0, + 0, 2, 0, 10, 0, 0, 6, 0, + 0, 4, 0, 12, 0, 0, 8, 0, + 0, 5, 0, 0, 2, 0, 10, 0, + 0, 6, 0, 0, 5, 0, 13, 0, + 0, 9, 0, 0, 5, 0, 13, 0, + 0, 11, 0, 0, 7, 0, 0, 3, + 0, 13, 0, 0, 8, 0, 0, 6, + 0, 0, 2, 0, 10, 0, 0, 7, + 0, 0, 4, 0, 12, 0, 0, 8, + 0, 0, 6, 0, 0, 3, 0, 11, + 0, 0, 7, 0, 0, 3, 0, 13, + 0, 0, 9, 0, 0, 5, 0, 0, + 3, 0, 10, 0, 0, 7, 0, 0, + 4, 0, 12, 0, 0, 9, 0, 0, + 5, 0, 0, 3, 0, 10, 0, 0, + 7, 0, 0, 4, 0, 12, 0, 0, + 9, 0, 0, 5, 0, 0, 3, 0, + 11, 0, 0, 7, 0, 0, 5, 0, + 12, 0, 0, 9, 0, 0, 5, 0, + 0, 2, 0, 12, 0, 0, 7, 0, + 0, 4, 0, 12, 0, 0, 8, 0, + 0, 6, 0, 0, 4, 0, 8, 0, + 0, 7, 0, 0, 5, 0, 0, 3, + 0, 8, 0, 0, 6, 0, 0, 4, + 0, 9, 0, 0, 7, 0, 0, 5, + 0, 0, 4, 0, 8, 0, 0, 6, + 0, 0, 4, 0, 8, 0, 0, 7, + 0, 0, 5, 0, 0, 4, 0, 8, + 0, 0, 6, 0, 0, 4, 0, 9, + 0, 0, 7, 0, 0, 5, 0, 0, + 4, 0, 8, 0, 0, 6, 0, 0, + 5, 0, 10, 0, 0, 7, 0, 0, + 5, 0, 0, 4, 0, 8, 0, 0, + 6, 0, 0, 5, 0, 10, 0, 0, + 7, 0, 0, 6, 0, 0, 3, 0, + 8, 0, 0, 6, 0, 0, 4, 0, + 11, 0, 0, 7, 0, 0, 6, 0, + 0, 4, 0, 8, 0, 0, 6, 0, + 0, 5, 0, 0, 3, 0, 7, 0, + 0, 5, 0, 0, 3, 0, 7, 0, + 0, 6, 0, 0, 4, 0, 0, 3, + 0, 7, 0, 0, 5, 0, 0, 4, + 0, 8, 0, 0, 6, 0, 0, 5, + 0, 10, 0, 0, 7, 0, 0, 5, + 0, 0, 4, 0, 8, 0, 0, 6, + 0, 0, 5, 0, 9, 0, 0, 8, + 0, 0, 6, 0, 0, 4, 0, 9, + 0, 0, 6, 0, 0, 5, 0, 11, + 0, 0, 7, 0, 0, 6, 0, 0, + 4, 0, 8, 0, 0, 6, 0, 0, + 5, 0, 0, 3, 0, 7, 0, 0, + 6, 0, 0, 4, 0, 9, 0, 0, + 6, 0, 0, 5, 0, 0, 3, 0, + 7, 0, 0, 6, 0, 0, 3, 0, + 8, 0, 0, 6, 0, 0, 5, 0, + 0, 3, 0, 7, 0, 0, 6, 0, + 0, 4, 0, 8, 0, 0, 7, 0, + 0, 5, 0, 0, 3, 0, 8, 0, + 0, 6, 0, 0, 4, 0, 9, 0, + 0, 7, 0, 0, 5, 0, 0, 4, + 0, 8, 0, 0, 6, 0, 0, 5, + 0, 9, 0, 0, 7, 0, 0, 5, + 0, 11, 0, 0, 7, 0, 0, 6, + 0, 0, 4, 0, 9, 0, 0, 6, + 0, 0, 5, 0, 0, 3, 0, 8, + 0, 0, 6, 0, 0, 4, 0, 10, + 0, 0, 6, 0, 0, 5, 0, 0, + 3, 0, 7, 0, 0, 6, 0, 0, + 4, 0, 12, 0, 0, 7, 0, 0, + 6, 0, 0, 3, 0, 8, 0, 0, + 6, 0, 0, 4, +} diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go index 0b612ca..994f2d0 100644 --- a/v2/kr/kr_holidays_test.go +++ b/v2/kr/kr_holidays_test.go @@ -110,14 +110,21 @@ func Example_lunar() { // gregorian: 2020-02-23 ~ 2020-03-23 // korean lunar: 2020-01-30 ~ 2020-02-29 // chinese lunar: 2020-02-01 ~ 2020-02-30 - fmt.Println(Sol2Lun(d(2020, 2, 22))) - fmt.Println(Sol2Lun(d(2020, 2, 23))) - fmt.Println(Sol2Lun(d(2020, 3, 2))) - fmt.Println(Sol2Lun(d(2020, 5, 5))) // leap month + + fmt.Println(Solar2Lunar(d(2020, 2, 22))) + fmt.Println(Solar2Lunar(d(2020, 2, 23))) + fmt.Println(Solar2Lunar(d(2020, 3, 2))) + fmt.Println(Solar2Lunar(d(2020, 5, 5))) + fmt.Println(Solar2Lunar(d(2020, 5, 23))) + fmt.Println(Solar2Lunar(d(2020, 6, 20))) + fmt.Println(Solar2Lunar(d(2020, 6, 21))) // Output: // [2020 1 29] false // [2020 1 30] false // [2020 2 8] false - // [2020 4 13] true + // [2020 4 13] false + // [2020 4 1] true + // [2020 4 29] true + // [2020 5 1] false } diff --git a/v2/kr/lunar.go b/v2/kr/lunar.go index 269f3c0..018e8ab 100644 --- a/v2/kr/lunar.go +++ b/v2/kr/lunar.go @@ -4,6 +4,8 @@ package kr // cause upon package does not export functions. import ( + "log" + "sort" "time" ) @@ -22,6 +24,7 @@ const ( // } // Sol2Lun converts to lunar year/month/day and if it is belongs to the leap month +// Chinese lunar calendar func Sol2Lun(t time.Time) (ymd [3]int, isLeap bool) { offset := offsetDays(MINDATE, t) year, offset := lunarYearByOffset(offset) @@ -134,3 +137,58 @@ func getLunarInfo(year int) int { } return LunarInfoList[idx] } + +// Solar2Lunar converts to lunar year/month/day and if it is belongs to the leap month +// Korean lunar calendar +func Solar2Lunar(t time.Time) (ymd [3]int, isLeap bool) { + const ( + BASEYEAR = 1391 + MINDATE = 2229156 // 1391-02-05 ( lunisolar 1391-01-01 ) + MAXDATE = 2470172 // 2050-12-31 ( lunisolar 2050-11-18 ) + ) + + // TODO gregorian 1582-10~05 ~ 1582-10-14 dates do not exist. + days := julian(t) + if days < MINDATE || days > MAXDATE { + log.Fatalf("The date is out of range: %d", days) + } + + days -= MINDATE + month := sort.Search(len(MonthTable), func(i int) bool { return MonthTable[i] > days }) - 1 + if month > len(MonthTable)-1 { + log.Fatalf("Out of MonthTable range: %d/%d", month, len(MonthTable)) + } + + year := sort.Search(len(YearTable), func(i int) bool { return YearTable[i] > month }) - 1 + if year > len(YearTable)-1 { + log.Fatalf("Out of YearTable range: %d/%d", year, len(YearTable)) + } + + var day int + month, day = month-YearTable[year]+1, days-MonthTable[month]+1 + if LeapTable[year] != 0 && LeapTable[year] <= month { + if LeapTable[year] == month { + isLeap = true + } else { + isLeap = false + } + month-- + } else { + isLeap = false + } + + ymd[0], ymd[1], ymd[2] = year+BASEYEAR, month, day + return ymd, isLeap +} + +// julian https://github.com/toelsiba/date/blob/master/julian_day.go +// Gregorian calendar starting from October 15, 1582 +// Algorithm from Henry F. Fliegel and Thomas C. Van Flandern +func julian(t time.Time) (jd int) { + year, month, day := t.Year(), int(t.Month()), t.Day() + e := (1461 * (year + 4800 + (month-14)/12)) / 4 + e += (367 * (month - 2 - 12*((month-14)/12))) / 12 + e += -(3 * ((year + 4900 + (month-14)/12) / 100)) / 4 + e += day - 32075 + return e +} From 78de12ff6280ce4befca6380009ec1761ea1d86e Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Wed, 17 Mar 2021 00:30:25 +0900 Subject: [PATCH 5/9] Add kr.Lunar2Solar --- v2/kr/lunar.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/v2/kr/lunar.go b/v2/kr/lunar.go index 018e8ab..c507218 100644 --- a/v2/kr/lunar.go +++ b/v2/kr/lunar.go @@ -7,6 +7,8 @@ import ( "log" "sort" "time" + + "github.com/rickar/cal/v2" ) const ( @@ -17,15 +19,10 @@ const ( MAXYEAR = 2100 ) -// Lun2Sol converts to solar calendar time -// TODO: implement if needed -// func Lun2Sol(year, month, day int) time.Time { -// return time.Now() -// } - // Sol2Lun converts to lunar year/month/day and if it is belongs to the leap month // Chinese lunar calendar func Sol2Lun(t time.Time) (ymd [3]int, isLeap bool) { + offset := offsetDays(MINDATE, t) year, offset := lunarYearByOffset(offset) leapMonth := leapMonth(year) @@ -181,6 +178,54 @@ func Solar2Lunar(t time.Time) (ymd [3]int, isLeap bool) { return ymd, isLeap } +// Lunar2Solar converts to solar calendar time +func Lunar2Solar(year, month, day int, isLeap bool) time.Time { + const ( + BASEYEAR = 1391 + MINDATE = 2229156 // 1391-02-05 ( lunisolar 1391-01-01 ) + MAXDATE = 2470172 // 2050-12-31 ( lunisolar 2050-11-18 ) + ) + + year -= BASEYEAR + if year < 0 || year >= len(YearTable) { + log.Fatal("Year is out of range") + } + + if month < 1 || month > 12 { + log.Fatal("Month is out of range") + } + + if isLeap && LeapTable[year]-1 != month { + log.Fatal("Wrong leap month") + } + + months := YearTable[year] + month - 1 + if isLeap && month+1 == LeapTable[year] { + months++ + } else if LeapTable[year] != 0 && LeapTable[year] < month { + months++ + } + + days := MonthTable[months] + day - 1 + if day < 1 || days >= MonthTable[months+1] { + log.Fatal("Wrong day") + } + + y, m, d := julianDayToDate(days + MINDATE) + return time.Date(y, time.Month(m), d, 0, 0, 0, 0, cal.DefaultLoc) +} + +func julianDayToDate(jd int) (year, month, day int) { + if jd >= 0 { + if jd >= 2299161 { + year, month, day = julianDayToGregorianDate(jd) + } else { + year, month, day = julianDayToJulianDate(jd) + } + } + return +} + // julian https://github.com/toelsiba/date/blob/master/julian_day.go // Gregorian calendar starting from October 15, 1582 // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern @@ -192,3 +237,35 @@ func julian(t time.Time) (jd int) { e += day - 32075 return e } + +// Julian calendar until October 4, 1582 +// Algorithm from Frequently Asked Questions about Calendars by Claus Toendering +func julianDayToJulianDate(jd int) (year, month, day int) { + jd += 32082 + dd := (4*jd + 3) / 1461 + ee := jd - (1461*dd)/4 + mm := ((5 * ee) + 2) / 153 + day = ee - (153*mm+2)/5 + 1 + month = mm + 3 - 12*(mm/10) + year = dd - 4800 + (mm / 10) + if year <= 0 { + year-- + } + return +} + +// Gregorian calendar starting from October 15, 1582 +// This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern +func julianDayToGregorianDate(jd int) (year, month, day int) { + ell := uint64(jd) + 68569 + n := (4 * ell) / 146097 + ell = ell - (146097*n+3)/4 + i := (4000 * (ell + 1)) / 1461001 + ell = ell - (1461*i)/4 + 31 + j := (80 * ell) / 2447 + day = int(ell - (2447*j)/80) + ell = j / 11 + month = int(j + 2 - (12 * ell)) + year = int(100*(n-49) + i + ell) + return +} From aae390c2f75ac2f6cb164ab2327adacf2bfb4602 Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Wed, 17 Mar 2021 00:30:57 +0900 Subject: [PATCH 6/9] Add `Lunar` attribute to Holiday struct --- v2/holiday.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v2/holiday.go b/v2/holiday.go index d748aeb..919b6b2 100644 --- a/v2/holiday.go +++ b/v2/holiday.go @@ -50,6 +50,7 @@ type Holiday struct { Julian bool // the holiday is based on a Julian calendar Observed []AltDay // the substitution days for the holiday Func HolidayFn // logic used to determine occurrences + Lunar bool // the holiday is based on a Lunar calendar } // Clone returns a copy of the Holiday. If overrides is non-nil, then the @@ -71,6 +72,7 @@ func (h *Holiday) Clone(overrides *Holiday) *Holiday { Offset: h.Offset, CalcOffset: h.CalcOffset, Julian: h.Julian, + Lunar: h.Lunar, Observed: h.Observed, Func: h.Func, } From 5637d83f867fc7d4c5290b417c349c5aaf8b7e66 Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Wed, 17 Mar 2021 00:31:40 +0900 Subject: [PATCH 7/9] add LunarNewYear Holiday to kr --- v2/kr/kr_holidays.go | 214 ++++++++++++++++++++------------------ v2/kr/kr_holidays_test.go | 9 ++ 2 files changed, 123 insertions(+), 100 deletions(-) diff --git a/v2/kr/kr_holidays.go b/v2/kr/kr_holidays.go index 87234b8..962e0fa 100644 --- a/v2/kr/kr_holidays.go +++ b/v2/kr/kr_holidays.go @@ -4,108 +4,122 @@ package kr import ( - "time" + "time" - "github.com/rickar/cal/v2" - "github.com/rickar/cal/v2/aa" + "github.com/rickar/cal/v2" + "github.com/rickar/cal/v2/aa" ) var ( - // Standard KR weekend substitution rules: - // https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98_%EA%B3%B5%ED%9C%B4%EC%9D%BC - // If the Lunar New Year holiday and Chuseok holiday overlap with other public holidays, including Sundays, - // the first weekday after the holiday shall be an alternative holiday, and if Children's Day overlaps with other - // public holidays or Saturdays, the first weekday shall be an alternative holiday (Article 3.[1] New November 5, 2013). - - // 설날 연휴와 추석 연휴가 일요일을 포함한 다른 공휴일과 겹칠 경우에는 연휴 다음 첫번째 평일을 대체공휴일로 하고, - // 어린이날이 다른 공휴일이나 토요일과 겹칠 경우에는 그 다음 첫번째 평일을 대체공휴일로 한다. - // (관공서의 공휴일에 관한 규정 제3조.[1] 2013년 11월 5일 신설) - - // Saturdays and Sundays move to next weekday - - weekendAlt = []cal.AltDay{ - {Day: time.Saturday, Offset: 2}, - {Day: time.Sunday, Offset: 1}, - } - - // NewYear represents New Year's Day on 1-Jan - NewYear = aa.NewYear.Clone(&cal.Holiday{Name: "새해 첫날", Type: cal.ObservancePublic}) - - // TODO: 설날 LunarNewYear - // Observed: weekendAlt, - - // IndependenceMovementDay represents 3.1절 on the 1-Mar - IndependenceMovementDay = &cal.Holiday{ - Name: "3.1절", - Type: cal.ObservancePublic, - Month: time.March, - Day: 1, - Func: cal.CalcDayOfMonth, - } - - // ChildrensDay represents 어린이날 on the 5-May - ChildrensDay = &cal.Holiday{ - Name: "어린이날", - Type: cal.ObservancePublic, - Month: time.May, - Day: 5, - Observed: weekendAlt, - Func: cal.CalcDayOfMonth, - } - - // TODO: 부처님 오신 날 lunar - - // MemorialDay represents 현충일 on the 6-June - MemorialDay = &cal.Holiday{ - Name: "현충일", - Type: cal.ObservancePublic, - Month: time.June, - Day: 6, - Func: cal.CalcDayOfMonth, - } - - // LiberationDay represents 광복절 on the 15-August - LiberationDay = &cal.Holiday{ - Name: "광복절", - Type: cal.ObservancePublic, - Month: time.August, - Day: 15, - Func: cal.CalcDayOfMonth, - } - - // TODO: 추석 lunar Chuseok - // Observed: weekendAlt, - - // FoundationDay represents 개천절 on the 3-October - FoundationDay = &cal.Holiday{ - Name: "개천절", - Type: cal.ObservancePublic, - Month: time.October, - Day: 3, - Func: cal.CalcDayOfMonth, - } - - // HangeulDay represents 개천절 on the 9-October - HangeulDay = &cal.Holiday{ - Name: "한글날", - Type: cal.ObservancePublic, - Month: time.October, - Day: 9, - Func: cal.CalcDayOfMonth, - } - - // ChristmasDay represents 성탄절 on the 25-Dec - ChristmasDay = aa.ChristmasDay.Clone(&cal.Holiday{Name: "성탄절", Type: cal.ObservancePublic}) - - // Holidays provides a list of the standard national holidays - Holidays = []*cal.Holiday{ - NewYear, - IndependenceMovementDay, - ChildrensDay, - MemorialDay, - LiberationDay, - FoundationDay, - HangeulDay, - ChristmasDay, - } + // Standard KR weekend substitution rules: + // https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98_%EA%B3%B5%ED%9C%B4%EC%9D%BC + // If the Lunar New Year holiday and Chuseok holiday overlap with other public holidays, including Sundays, + // the first weekday after the holiday shall be an alternative holiday, and if Children's Day overlaps with other + // public holidays or Saturdays, the first weekday shall be an alternative holiday (Article 3.[1] New November 5, 2013). + + // 설날 연휴와 추석 연휴가 일요일을 포함한 다른 공휴일과 겹칠 경우에는 연휴 다음 첫번째 평일을 대체공휴일로 하고, + // 어린이날이 다른 공휴일이나 토요일과 겹칠 경우에는 그 다음 첫번째 평일을 대체공휴일로 한다. + // (관공서의 공휴일에 관한 규정 제3조.[1] 2013년 11월 5일 신설) + + // Saturdays and Sundays move to next weekday + + weekendAlt = []cal.AltDay{ + {Day: time.Saturday, Offset: 2}, + {Day: time.Sunday, Offset: 1}, + } + + // NewYear represents New Year's Day on 1-Jan + NewYear = aa.NewYear.Clone(&cal.Holiday{Name: "새해 첫날", Type: cal.ObservancePublic}) + + // LunarNewYear represents 설날 on the Lunar 1-Jan + LunarNewYear = &cal.Holiday{ + Name: "설날", + Type: cal.ObservancePublic, + Month: time.January, + Day: 1, + Lunar: true, + Observed: weekendAlt, + Func: CalcDayOfLunarMonth, + } + + // IndependenceMovementDay represents 3.1절 on the 1-Mar + IndependenceMovementDay = &cal.Holiday{ + Name: "3.1절", + Type: cal.ObservancePublic, + Month: time.March, + Day: 1, + Func: cal.CalcDayOfMonth, + } + + // ChildrensDay represents 어린이날 on the 5-May + ChildrensDay = &cal.Holiday{ + Name: "어린이날", + Type: cal.ObservancePublic, + Month: time.May, + Day: 5, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // TODO: 부처님 오신 날 lunar + + // MemorialDay represents 현충일 on the 6-June + MemorialDay = &cal.Holiday{ + Name: "현충일", + Type: cal.ObservancePublic, + Month: time.June, + Day: 6, + Func: cal.CalcDayOfMonth, + } + + // LiberationDay represents 광복절 on the 15-August + LiberationDay = &cal.Holiday{ + Name: "광복절", + Type: cal.ObservancePublic, + Month: time.August, + Day: 15, + Func: cal.CalcDayOfMonth, + } + + // TODO: 추석 lunar Chuseok + // Observed: weekendAlt, + + // FoundationDay represents 개천절 on the 3-October + FoundationDay = &cal.Holiday{ + Name: "개천절", + Type: cal.ObservancePublic, + Month: time.October, + Day: 3, + Func: cal.CalcDayOfMonth, + } + + // HangeulDay represents 개천절 on the 9-October + HangeulDay = &cal.Holiday{ + Name: "한글날", + Type: cal.ObservancePublic, + Month: time.October, + Day: 9, + Func: cal.CalcDayOfMonth, + } + + // ChristmasDay represents 성탄절 on the 25-Dec + ChristmasDay = aa.ChristmasDay.Clone(&cal.Holiday{Name: "성탄절", Type: cal.ObservancePublic}) + + // Holidays provides a list of the standard national holidays + Holidays = []*cal.Holiday{ + NewYear, + IndependenceMovementDay, + ChildrensDay, + MemorialDay, + LiberationDay, + FoundationDay, + HangeulDay, + ChristmasDay, + } ) + +// CalcDayOfLunarMonth calculates the occurrence of a holiday that is always a +// specific day of the month such as the 5th of November. +func CalcDayOfLunarMonth(h *cal.Holiday, year int) time.Time { + return Lunar2Solar(year, int(h.Month), h.Day, false) +} diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go index 994f2d0..74672a3 100644 --- a/v2/kr/kr_holidays_test.go +++ b/v2/kr/kr_holidays_test.go @@ -30,6 +30,15 @@ func TestHolidays(t *testing.T) { {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, + {LunarNewYear, 2015, d(2015, 2, 19), d(2015, 2, 19)}, + {LunarNewYear, 2016, d(2016, 2, 8), d(2016, 2, 8)}, + {LunarNewYear, 2017, d(2017, 1, 28), d(2017, 1, 30)}, + {LunarNewYear, 2018, d(2018, 2, 16), d(2018, 2, 16)}, + {LunarNewYear, 2019, d(2019, 2, 5), d(2019, 2, 5)}, + {LunarNewYear, 2020, d(2020, 1, 25), d(2020, 1, 27)}, + {LunarNewYear, 2021, d(2021, 2, 12), d(2021, 2, 12)}, + {LunarNewYear, 2022, d(2022, 2, 1), d(2022, 2, 1)}, + {IndependenceMovementDay, 2015, d(2015, 3, 1), d(2015, 3, 1)}, {IndependenceMovementDay, 2016, d(2016, 3, 1), d(2016, 3, 1)}, {IndependenceMovementDay, 2017, d(2017, 3, 1), d(2017, 3, 1)}, From 784f3d645b79060c1192b7de5ce96b311ba405fe Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Wed, 17 Mar 2021 00:49:05 +0900 Subject: [PATCH 8/9] add test for kr.Lunar holidays --- v2/kr/kr_holidays.go | 32 ++++++++++++++++++++++++++++---- v2/kr/kr_holidays_test.go | 17 +++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/v2/kr/kr_holidays.go b/v2/kr/kr_holidays.go index 962e0fa..d9749f5 100644 --- a/v2/kr/kr_holidays.go +++ b/v2/kr/kr_holidays.go @@ -28,6 +28,11 @@ var ( {Day: time.Sunday, Offset: 1}, } + LunarNewYearChuseokAlt = []cal.AltDay{ + {Day: time.Saturday, Offset: 2}, + {Day: time.Sunday, Offset: 2}, + } + // NewYear represents New Year's Day on 1-Jan NewYear = aa.NewYear.Clone(&cal.Holiday{Name: "새해 첫날", Type: cal.ObservancePublic}) @@ -38,7 +43,7 @@ var ( Month: time.January, Day: 1, Lunar: true, - Observed: weekendAlt, + Observed: LunarNewYearChuseokAlt, Func: CalcDayOfLunarMonth, } @@ -61,7 +66,15 @@ var ( Func: cal.CalcDayOfMonth, } - // TODO: 부처님 오신 날 lunar + // BuddhasDay represents 부처님 오신 날 on the Lunar 8-April + BuddhasDay = &cal.Holiday{ + Name: "부처님 오신 날", + Type: cal.ObservancePublic, + Month: time.April, + Day: 8, + Lunar: true, + Func: CalcDayOfLunarMonth, + } // MemorialDay represents 현충일 on the 6-June MemorialDay = &cal.Holiday{ @@ -81,8 +94,16 @@ var ( Func: cal.CalcDayOfMonth, } - // TODO: 추석 lunar Chuseok - // Observed: weekendAlt, + // Chuseok represents 추석 on the Lunar 15-August + Chuseok = &cal.Holiday{ + Name: "추석", + Type: cal.ObservancePublic, + Month: time.August, + Day: 15, + Lunar: true, + Observed: LunarNewYearChuseokAlt, + Func: CalcDayOfLunarMonth, + } // FoundationDay represents 개천절 on the 3-October FoundationDay = &cal.Holiday{ @@ -108,10 +129,13 @@ var ( // Holidays provides a list of the standard national holidays Holidays = []*cal.Holiday{ NewYear, + LunarNewYear, IndependenceMovementDay, + BuddhasDay, ChildrensDay, MemorialDay, LiberationDay, + Chuseok, FoundationDay, HangeulDay, ChristmasDay, diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go index 74672a3..d96ee8b 100644 --- a/v2/kr/kr_holidays_test.go +++ b/v2/kr/kr_holidays_test.go @@ -48,6 +48,15 @@ func TestHolidays(t *testing.T) { {IndependenceMovementDay, 2021, d(2021, 3, 1), d(2021, 3, 1)}, {IndependenceMovementDay, 2022, d(2022, 3, 1), d(2022, 3, 1)}, + {BuddhasDay, 2015, d(2015, 5, 25), d(2015, 5, 25)}, + {BuddhasDay, 2016, d(2016, 5, 14), d(2016, 5, 14)}, + {BuddhasDay, 2017, d(2017, 5, 3), d(2017, 5, 3)}, + {BuddhasDay, 2018, d(2018, 5, 22), d(2018, 5, 22)}, + {BuddhasDay, 2019, d(2019, 5, 12), d(2019, 5, 12)}, + {BuddhasDay, 2020, d(2020, 4, 30), d(2020, 4, 30)}, + {BuddhasDay, 2021, d(2021, 5, 19), d(2021, 5, 19)}, + {BuddhasDay, 2022, d(2022, 5, 8), d(2022, 5, 8)}, + {ChildrensDay, 2015, d(2015, 5, 5), d(2015, 5, 5)}, {ChildrensDay, 2016, d(2016, 5, 5), d(2016, 5, 5)}, {ChildrensDay, 2017, d(2017, 5, 5), d(2017, 5, 5)}, @@ -75,6 +84,14 @@ func TestHolidays(t *testing.T) { {LiberationDay, 2021, d(2021, 8, 15), d(2021, 8, 15)}, {LiberationDay, 2022, d(2022, 8, 15), d(2022, 8, 15)}, + {Chuseok, 2016, d(2016, 9, 15), d(2016, 9, 15)}, + {Chuseok, 2017, d(2017, 10, 4), d(2017, 10, 4)}, + {Chuseok, 2018, d(2018, 9, 24), d(2018, 9, 24)}, + {Chuseok, 2019, d(2019, 9, 13), d(2019, 9, 13)}, + {Chuseok, 2020, d(2020, 10, 1), d(2020, 10, 1)}, + {Chuseok, 2021, d(2021, 9, 21), d(2021, 9, 21)}, + {Chuseok, 2022, d(2022, 9, 10), d(2022, 9, 12)}, + {FoundationDay, 2015, d(2015, 10, 3), d(2015, 10, 3)}, {FoundationDay, 2016, d(2016, 10, 3), d(2016, 10, 3)}, {FoundationDay, 2017, d(2017, 10, 3), d(2017, 10, 3)}, From 14a5217402a41010d2c3ea11ac1dc8322a6895a0 Mon Sep 17 00:00:00 2001 From: Hyungsuk Hong Date: Wed, 17 Mar 2021 01:03:45 +0900 Subject: [PATCH 9/9] add rest of kr holidays - kr.BeforeLunarNewYear - kr.AfterLunarNewYear - kr.BeforeChuseok - kr.AfterChuseok --- v2/kr/kr_holidays.go | 56 +++++++++++++++++++++++++++++++++++++++ v2/kr/kr_holidays_test.go | 34 ++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/v2/kr/kr_holidays.go b/v2/kr/kr_holidays.go index d9749f5..e7dd016 100644 --- a/v2/kr/kr_holidays.go +++ b/v2/kr/kr_holidays.go @@ -36,6 +36,16 @@ var ( // NewYear represents New Year's Day on 1-Jan NewYear = aa.NewYear.Clone(&cal.Holiday{Name: "새해 첫날", Type: cal.ObservancePublic}) + // BeforeLunarNewYear represents 설전날 before on the Lunar 1-Jan + BeforeLunarNewYear = &cal.Holiday{ + Name: "설전날", + Type: cal.ObservancePublic, + Month: time.January, + Day: 1, + Lunar: true, + Func: CalcBeforeDayOfLunarMonth, + } + // LunarNewYear represents 설날 on the Lunar 1-Jan LunarNewYear = &cal.Holiday{ Name: "설날", @@ -47,6 +57,16 @@ var ( Func: CalcDayOfLunarMonth, } + // AfterLunarNewYear represents 설다음날 after on the Lunar 1-Jan + AfterLunarNewYear = &cal.Holiday{ + Name: "설다음날", + Type: cal.ObservancePublic, + Month: time.January, + Day: 1, + Lunar: true, + Func: CalcAfterDayOfLunarMonth, + } + // IndependenceMovementDay represents 3.1절 on the 1-Mar IndependenceMovementDay = &cal.Holiday{ Name: "3.1절", @@ -94,6 +114,16 @@ var ( Func: cal.CalcDayOfMonth, } + // BeforeChuseok represents 추석전날 before on the Lunar 15-August + BeforeChuseok = &cal.Holiday{ + Name: "추석전날", + Type: cal.ObservancePublic, + Month: time.August, + Day: 15, + Lunar: true, + Func: CalcBeforeDayOfLunarMonth, + } + // Chuseok represents 추석 on the Lunar 15-August Chuseok = &cal.Holiday{ Name: "추석", @@ -105,6 +135,16 @@ var ( Func: CalcDayOfLunarMonth, } + // AfterChuseok represents 추석전날 after on the Lunar 15-August + AfterChuseok = &cal.Holiday{ + Name: "추석다음날", + Type: cal.ObservancePublic, + Month: time.August, + Day: 15, + Lunar: true, + Func: CalcAfterDayOfLunarMonth, + } + // FoundationDay represents 개천절 on the 3-October FoundationDay = &cal.Holiday{ Name: "개천절", @@ -129,13 +169,17 @@ var ( // Holidays provides a list of the standard national holidays Holidays = []*cal.Holiday{ NewYear, + BeforeLunarNewYear, LunarNewYear, + AfterLunarNewYear, IndependenceMovementDay, BuddhasDay, ChildrensDay, MemorialDay, LiberationDay, + BeforeChuseok, Chuseok, + AfterChuseok, FoundationDay, HangeulDay, ChristmasDay, @@ -147,3 +191,15 @@ var ( func CalcDayOfLunarMonth(h *cal.Holiday, year int) time.Time { return Lunar2Solar(year, int(h.Month), h.Day, false) } + +// CalcBeforeDayOfLunarMonth a before day of specific LunarDate. +// 1/1 before day maybe become 12/29 or 12/30 +// so treat before day as solar calendar +func CalcBeforeDayOfLunarMonth(h *cal.Holiday, year int) time.Time { + return Lunar2Solar(year, int(h.Month), h.Day, false).Add(time.Hour * 24 * -1) +} + +// CalcAfterDayOfLunarMonth a after day of specific LunarDate. +func CalcAfterDayOfLunarMonth(h *cal.Holiday, year int) time.Time { + return Lunar2Solar(year, int(h.Month), h.Day, false).Add(time.Hour * 24) +} diff --git a/v2/kr/kr_holidays_test.go b/v2/kr/kr_holidays_test.go index d96ee8b..956f52d 100644 --- a/v2/kr/kr_holidays_test.go +++ b/v2/kr/kr_holidays_test.go @@ -30,6 +30,15 @@ func TestHolidays(t *testing.T) { {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, + {BeforeLunarNewYear, 2015, d(2015, 2, 18), d(2015, 2, 18)}, + {BeforeLunarNewYear, 2016, d(2016, 2, 7), d(2016, 2, 7)}, + {BeforeLunarNewYear, 2017, d(2017, 1, 27), d(2017, 1, 27)}, + {BeforeLunarNewYear, 2018, d(2018, 2, 15), d(2018, 2, 15)}, + {BeforeLunarNewYear, 2019, d(2019, 2, 4), d(2019, 2, 4)}, + {BeforeLunarNewYear, 2020, d(2020, 1, 24), d(2020, 1, 24)}, + {BeforeLunarNewYear, 2021, d(2021, 2, 11), d(2021, 2, 11)}, + {BeforeLunarNewYear, 2022, d(2022, 1, 31), d(2022, 1, 31)}, + {LunarNewYear, 2015, d(2015, 2, 19), d(2015, 2, 19)}, {LunarNewYear, 2016, d(2016, 2, 8), d(2016, 2, 8)}, {LunarNewYear, 2017, d(2017, 1, 28), d(2017, 1, 30)}, @@ -39,6 +48,15 @@ func TestHolidays(t *testing.T) { {LunarNewYear, 2021, d(2021, 2, 12), d(2021, 2, 12)}, {LunarNewYear, 2022, d(2022, 2, 1), d(2022, 2, 1)}, + {AfterLunarNewYear, 2015, d(2015, 2, 20), d(2015, 2, 20)}, + {AfterLunarNewYear, 2016, d(2016, 2, 9), d(2016, 2, 9)}, + {AfterLunarNewYear, 2017, d(2017, 1, 29), d(2017, 1, 29)}, + {AfterLunarNewYear, 2018, d(2018, 2, 17), d(2018, 2, 17)}, + {AfterLunarNewYear, 2019, d(2019, 2, 6), d(2019, 2, 6)}, + {AfterLunarNewYear, 2020, d(2020, 1, 26), d(2020, 1, 26)}, + {AfterLunarNewYear, 2021, d(2021, 2, 13), d(2021, 2, 13)}, + {AfterLunarNewYear, 2022, d(2022, 2, 2), d(2022, 2, 2)}, + {IndependenceMovementDay, 2015, d(2015, 3, 1), d(2015, 3, 1)}, {IndependenceMovementDay, 2016, d(2016, 3, 1), d(2016, 3, 1)}, {IndependenceMovementDay, 2017, d(2017, 3, 1), d(2017, 3, 1)}, @@ -84,6 +102,14 @@ func TestHolidays(t *testing.T) { {LiberationDay, 2021, d(2021, 8, 15), d(2021, 8, 15)}, {LiberationDay, 2022, d(2022, 8, 15), d(2022, 8, 15)}, + {BeforeChuseok, 2016, d(2016, 9, 14), d(2016, 9, 14)}, + {BeforeChuseok, 2017, d(2017, 10, 3), d(2017, 10, 3)}, + {BeforeChuseok, 2018, d(2018, 9, 23), d(2018, 9, 23)}, + {BeforeChuseok, 2019, d(2019, 9, 12), d(2019, 9, 12)}, + {BeforeChuseok, 2020, d(2020, 9, 30), d(2020, 9, 30)}, + {BeforeChuseok, 2021, d(2021, 9, 20), d(2021, 9, 20)}, + {BeforeChuseok, 2022, d(2022, 9, 9), d(2022, 9, 9)}, + {Chuseok, 2016, d(2016, 9, 15), d(2016, 9, 15)}, {Chuseok, 2017, d(2017, 10, 4), d(2017, 10, 4)}, {Chuseok, 2018, d(2018, 9, 24), d(2018, 9, 24)}, @@ -92,6 +118,14 @@ func TestHolidays(t *testing.T) { {Chuseok, 2021, d(2021, 9, 21), d(2021, 9, 21)}, {Chuseok, 2022, d(2022, 9, 10), d(2022, 9, 12)}, + {AfterChuseok, 2016, d(2016, 9, 16), d(2016, 9, 16)}, + {AfterChuseok, 2017, d(2017, 10, 5), d(2017, 10, 5)}, + {AfterChuseok, 2018, d(2018, 9, 25), d(2018, 9, 25)}, + {AfterChuseok, 2019, d(2019, 9, 14), d(2019, 9, 14)}, + {AfterChuseok, 2020, d(2020, 10, 2), d(2020, 10, 2)}, + {AfterChuseok, 2021, d(2021, 9, 22), d(2021, 9, 22)}, + {AfterChuseok, 2022, d(2022, 9, 11), d(2022, 9, 11)}, + {FoundationDay, 2015, d(2015, 10, 3), d(2015, 10, 3)}, {FoundationDay, 2016, d(2016, 10, 3), d(2016, 10, 3)}, {FoundationDay, 2017, d(2017, 10, 3), d(2017, 10, 3)},