diff --git a/README.md b/README.md index dad62fd..7413b56 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ const ( ) ``` -## Usage +## 簡単な使い方 ```go start, _ := koyomi.DateFrom("2019-05-01") @@ -53,6 +53,176 @@ io.Copy(os.Stdout, bytes.NewReader(csv)) //"2019-05-21","小満" ``` +## おまけ機能 + +### 西暦⇔和暦 変換 + +元号を含む和暦と西暦との変換を行います。 +元号は以下のものに対応しています。 + +| 元号 | 起点 | +| ---------------- | -------------- | +| 明治(改暦以降) | 1873年1月1日 | +| 大正 | 1912年7月30日 | +| 昭和 | 1926年12月25日 | +| 平成 | 1989年1月8日 | +| 令和 | 2019年5月1日 | + +#### 西暦から和暦への変換 + +```go +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "strconv" + "time" + + "github.com/goark/koyomi/era" +) + +func main() { + flag.Parse() + argsStr := flag.Args() + tm := time.Now() + if len(argsStr) > 0 { + if len(argsStr) < 3 { + fmt.Fprintln(os.Stderr, "年月日を指定してください") + return + } + args := make([]int, 3) + for i := 0; i < 3; i++ { + num, err := strconv.Atoi(argsStr[i]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + args[i] = num + } + tm = time.Date(args[0], time.Month(args[1]), args[2], 0, 0, 0, 0, time.Local) + } + te := era.New(tm) + n, y := te.YearEraString() + if len(n) == 0 { + fmt.Fprintln(os.Stderr, "正しい年月日を指定してください") + return + } + fmt.Printf("%s%s%d月%d日\n", n, y, te.Month(), te.Day()) +} +``` + +これを実行すると以下のような結果になります。 + +``` +$ go run era/sample1/sample1.go 2019 4 30 +平成31年4月30日 + +$ go run era/sample1/sample1.go 2019 5 1 +令和元年5月1日 +``` + +#### 和暦から西暦への変換 + +```go +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "strconv" + "time" + + "github.com/goark/koyomi/era" +) + +func main() { + flag.Parse() + argsStr := flag.Args() + + if len(argsStr) < 4 { + fmt.Fprintln(os.Stderr, "元号 年 月 日 を指定してください") + return + } + name := argsStr[0] + args := make([]int, 3) + for i := 0; i < 3; i++ { + num, err := strconv.Atoi(argsStr[i+1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + args[i] = num + } + te := era.Date(era.Name(name), args[0], time.Month(args[1]), args[2], 0, 0, 0, 0, time.Local) + fmt.Println(te.Format("西暦2006年1月2日")) +} +``` + +これを実行すると以下のような結果になります。 + +``` +$ go run sample2/sample2.go 平成 31 4 30 +西暦2019年4月30日 + +$ go run sample2/sample2.go 令和 1 5 1 +西暦2019年5月1日 +``` + +### 十干十二支を数え上げる + +```go +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "time" + + "github.com/goark/koyomi/zodiac" +) + +func main() { + flag.Parse() + args := flag.Args() + if len(args) < 1 { + fmt.Fprintln(os.Stderr, os.ErrInvalid) + return + } + for _, s := range args { + t, err := time.Parse("2006-01-02", s) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + kan, shi := zodiac.ZodiacYearNumber(t.Year()) + fmt.Printf("Year %v is %v%v\n", t.Year(), kan, shi) + kan, shi = zodiac.ZodiacDayNumber(t) + fmt.Printf("Day %v is %v%v\n", t.Format("2006-01-02"), kan, shi) + } +} +``` + +これを実行すると以下のような結果になります。 + +``` +$ go run zodiac/sample/sample.go 2021-07-28 +Year 2021 is 辛丑 +Day 2021-07-28 is 丁丑 +``` + ## Modules Requirement Graph [![dependency.png](./dependency.png)](./dependency.png) diff --git a/Taskfile.yml b/Taskfile.yml index 84b8e69..9086f6e 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -13,7 +13,7 @@ tasks: cmds: - go mod verify - go test -shuffle on ./... - - docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.45.0 golangci-lint run --enable gosec --timeout 3m0s ./... + - docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.45.2 golangci-lint run --enable gosec --timeout 3m0s ./... sources: - ./go.mod - '**/*.go' diff --git a/era/era.go b/era/era.go new file mode 100644 index 0000000..43ab6f0 --- /dev/null +++ b/era/era.go @@ -0,0 +1,131 @@ +package era + +import ( + "fmt" + "time" +) + +//era.eraName は元号名を表す型です。 +type eraName int + +const ( + Unknown eraName = iota //不明な元号 + Meiji //明治 + Taisho //大正 + Showa //昭和 + Heisei //平成 + Reiwa //令和 +) + +var eraString = map[eraName]string{ + Unknown: "", + Meiji: "明治", + Taisho: "大正", + Showa: "昭和", + Heisei: "平成", + Reiwa: "令和", +} + +//era.Name() 関数は元号の文字列から元号名 era.eraName を取得します。 +//該当する元号名がない場合は era.Unknown を返します。 +func Name(s string) eraName { + for k, v := range eraString { + if v == s { + return k + } + } + return Unknown +} + +func (e eraName) String() string { + if s, ok := eraString[e]; ok { + return s + } + return "" +} + +//err.Time は元号操作を含む時間クラスです。 +type Time struct { + time.Time +} + +var ( + locJST = time.FixedZone("JST", 9*60*60) //日本標準時 + eraTrigger = map[eraName]time.Time{ //各元号の起点 + Meiji: time.Date(1873, time.January, 1, 0, 0, 0, 0, locJST), //明治(の改暦) : 1873-01-01 + Taisho: time.Date(1912, time.July, 30, 0, 0, 0, 0, locJST), //大正 : 1912-07-30 + Showa: time.Date(1926, time.December, 25, 0, 0, 0, 0, locJST), //昭和 : 1926-12-25 + Heisei: time.Date(1989, time.January, 8, 0, 0, 0, 0, locJST), //平成 : 1989-01-08 + Reiwa: time.Date(2019, time.May, 1, 0, 0, 0, 0, locJST), //令和 : 2019-05-01 + } + eraSorted = []eraName{Reiwa, Heisei, Showa, Taisho, Meiji} //ソートされた元号の配列(降順) +) + +//era.New() 関数は era.Time インスタンスを生成します。 +func New(t time.Time) Time { + return Time{t.In(locJST)} //日本標準時で揃える +} + +//era.Date() 関数は 元号・年・月・日・時・分・秒・タイムゾーン を指定して era.Time 型のインスタンスを返します。 +//起点が定義されない元号を指定した場合は西暦として処理します。 +func Date(en eraName, year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) Time { + ofset := 0 + if dt, ok := eraTrigger[en]; ok { + ofset = dt.Year() - 1 + } + return New(time.Date(year+ofset, month, day, hour, min, sec, nsec, loc)) +} + +//era.Time.Era() メソッドは元号名 era.eraName のインスタンスを返します。 +//元号が不明の場合は era.Unknown を返します。 +func (t Time) Era() eraName { + for _, es := range eraSorted { + if !t.Before(eraTrigger[es]) { + return es + } + } + return Unknown + +} + +//era.Time.YearEra() メソッドは元号付きの年の値を返します。 +//元号が不明の場合は (era.Unknown, 0) を返します。 +func (t Time) YearEra() (eraName, int) { + era := t.Era() + if era == Unknown { + return Unknown, 0 + } + year := t.Year() - eraTrigger[era].Year() + 1 + if era == Meiji { //明治のみ5年のオフセットを加算する + return era, year + 5 + } + return era, year +} + +//era.Time.YearEraString() メソッドは元号付きの年の値を文字列で返します。 +//元号が不明の場合は空文字列を返します。 +func (t Time) YearEraString() (string, string) { + era, year := t.YearEra() + if era == Unknown || year < 1 { + return "", "" + } + if year == 1 { + return era.String(), "元年" + } + return era.String(), fmt.Sprintf("%d年", year) +} + +/* Copyright 2019-2022 Spiegel +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ diff --git a/era/era_test.go b/era/era_test.go new file mode 100644 index 0000000..d26858f --- /dev/null +++ b/era/era_test.go @@ -0,0 +1,118 @@ +package era + +import ( + "testing" + "time" +) + +func TestNameToString(t *testing.T) { + testCases := []struct { + n eraName + s string + }{ + {n: Unknown, s: ""}, + {n: Meiji, s: "明治"}, + {n: Taisho, s: "大正"}, + {n: Showa, s: "昭和"}, + {n: Heisei, s: "平成"}, + {n: Reiwa, s: "令和"}, + {n: eraName(6), s: ""}, + } + for _, tc := range testCases { + if tc.n.String() != tc.s { + t.Errorf("eraName.String(%d) = \"%v\", want \"%v\".", int(tc.n), tc.n, tc.s) + } + } +} + +func TestStringToName(t *testing.T) { + testCases := []struct { + n eraName + s string + }{ + {n: Unknown, s: ""}, + {n: Unknown, s: "元号"}, + {n: Meiji, s: "明治"}, + {n: Taisho, s: "大正"}, + {n: Showa, s: "昭和"}, + {n: Heisei, s: "平成"}, + {n: Reiwa, s: "令和"}, + } + for _, tc := range testCases { + n := Name(tc.s) + if tc.n != n { + t.Errorf("GetName(%v) = \"%v\", want \"%v\".", tc.s, n, tc.n) + } + } +} + +func TestTimeToEra(t *testing.T) { + testCases := []struct { + year int + month time.Month + day int + n eraName + yearEra int + eraStr string + yearStr string + }{ + {year: 1872, month: time.December, day: 31, n: Unknown, yearEra: 0, eraStr: "", yearStr: ""}, + {year: 1873, month: time.January, day: 1, n: Meiji, yearEra: 6, eraStr: "明治", yearStr: "6年"}, + {year: 1912, month: time.July, day: 29, n: Meiji, yearEra: 45, eraStr: "明治", yearStr: "45年"}, + {year: 1912, month: time.July, day: 30, n: Taisho, yearEra: 1, eraStr: "大正", yearStr: "元年"}, + {year: 1926, month: time.December, day: 24, n: Taisho, yearEra: 15, eraStr: "大正", yearStr: "15年"}, + {year: 1926, month: time.December, day: 25, n: Showa, yearEra: 1, eraStr: "昭和", yearStr: "元年"}, + {year: 1989, month: time.January, day: 7, n: Showa, yearEra: 64, eraStr: "昭和", yearStr: "64年"}, + {year: 1989, month: time.January, day: 8, n: Heisei, yearEra: 1, eraStr: "平成", yearStr: "元年"}, + {year: 2019, month: time.April, day: 30, n: Heisei, yearEra: 31, eraStr: "平成", yearStr: "31年"}, + {year: 2019, month: time.May, day: 1, n: Reiwa, yearEra: 1, eraStr: "令和", yearStr: "元年"}, + {year: 2118, month: time.December, day: 31, n: Reiwa, yearEra: 100, eraStr: "令和", yearStr: "100年"}, + } + for _, tc := range testCases { + tm := time.Date(tc.year, tc.month, tc.day, 0, 0, 0, 0, time.UTC) + n, y := New(tm).YearEra() + if tc.n != n || tc.yearEra != y { + t.Errorf("[%v].Era() = \"%v %d\", want \"%v %d\".", tm, n, y, tc.n, tc.yearEra) + } + ns, ys := New(tm).YearEraString() + if tc.eraStr != ns || tc.yearStr != ys { + t.Errorf("[%v].Era() = \"%v %v\", want \"%v %v\".", tm, ns, ys, tc.eraStr, tc.yearStr) + } + } +} + +func TestEraToDate(t *testing.T) { + testCases := []struct { + n eraName + year int + month time.Month + day int + timeStr string + }{ + {n: Unknown, year: 2019, month: time.May, day: 1, timeStr: "2019-05-01"}, + {n: Heisei, year: 31, month: time.May, day: 1, timeStr: "2019-05-01"}, + {n: Reiwa, year: 1, month: time.May, day: 1, timeStr: "2019-05-01"}, + } + for _, tc := range testCases { + tm := Date(tc.n, tc.year, tc.month, tc.day, 0, 0, 0, 0, time.UTC) + s := tm.Format("2006-01-02") + if tc.timeStr != s { + t.Errorf("Date() = \"%v\", want \"%v\".", s, tc.timeStr) + } + } +} + +/* Copyright 2019-2022 Spiegel +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ diff --git a/era/sample1/sample1.go b/era/sample1/sample1.go new file mode 100644 index 0000000..3f29e8b --- /dev/null +++ b/era/sample1/sample1.go @@ -0,0 +1,58 @@ +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "strconv" + "time" + + "github.com/goark/koyomi/era" +) + +func main() { + flag.Parse() + argsStr := flag.Args() + tm := time.Now() + if len(argsStr) > 0 { + if len(argsStr) < 3 { + fmt.Fprintln(os.Stderr, "年月日を指定してください") + return + } + args := make([]int, 3) + for i := 0; i < 3; i++ { + num, err := strconv.Atoi(argsStr[i]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + args[i] = num + } + tm = time.Date(args[0], time.Month(args[1]), args[2], 0, 0, 0, 0, time.Local) + } + te := era.New(tm) + n, y := te.YearEraString() + if len(n) == 0 { + fmt.Fprintln(os.Stderr, "正しい年月日を指定してください") + return + } + fmt.Printf("%s%s%d月%d日\n", n, y, te.Month(), te.Day()) +} + +/* Copyright 2019 Spiegel +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ diff --git a/era/sample2/sample2.go b/era/sample2/sample2.go new file mode 100644 index 0000000..87e93d0 --- /dev/null +++ b/era/sample2/sample2.go @@ -0,0 +1,51 @@ +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "strconv" + "time" + + "github.com/goark/koyomi/era" +) + +func main() { + flag.Parse() + argsStr := flag.Args() + + if len(argsStr) < 4 { + fmt.Fprintln(os.Stderr, "元号 年 月 日 を指定してください") + return + } + name := argsStr[0] + args := make([]int, 3) + for i := 0; i < 3; i++ { + num, err := strconv.Atoi(argsStr[i+1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + args[i] = num + } + te := era.Date(era.Name(name), args[0], time.Month(args[1]), args[2], 0, 0, 0, 0, time.Local) + fmt.Println(te.Format("西暦2006年1月2日")) +} + +/* Copyright 2019-2022 Spiegel +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ diff --git a/zodiac/sample/sample.go b/zodiac/sample/sample.go new file mode 100644 index 0000000..e342c2b --- /dev/null +++ b/zodiac/sample/sample.go @@ -0,0 +1,48 @@ +//go:build run +// +build run + +package main + +import ( + "flag" + "fmt" + "os" + "time" + + "github.com/goark/koyomi/zodiac" +) + +func main() { + flag.Parse() + args := flag.Args() + if len(args) < 1 { + fmt.Fprintln(os.Stderr, os.ErrInvalid) + return + } + for _, s := range args { + t, err := time.Parse("2006-01-02", s) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + kan, shi := zodiac.ZodiacYearNumber(t.Year()) + fmt.Printf("Year %v is %v%v\n", t.Year(), kan, shi) + kan, shi = zodiac.ZodiacDayNumber(t) + fmt.Printf("Day %v is %v%v\n", t.Format("2006-01-02"), kan, shi) + } +} + +/* Copyright 2021 Spiegel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/zodiac/zodiac.go b/zodiac/zodiac.go new file mode 100644 index 0000000..ca4bd53 --- /dev/null +++ b/zodiac/zodiac.go @@ -0,0 +1,98 @@ +package zodiac + +import "time" + +type Kan10 uint + +const ( + Kinoe Kan10 = iota // 甲(木の兄) + Kinoto // 乙(木の弟) + Hinoe // 丙(火の兄) + Hinoto // 丁(火の弟) + Tsutinoe // 戊(土の兄) + Tsutinoto // 己(土の弟) + Kanoe // 庚(金の兄) + Kanoto // 辛(金の弟) + Mizunoe // 壬(水の兄) + Mizunoto // 癸(水の弟) + KanMax +) + +var kanNames = [KanMax]string{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"} + +func (k Kan10) String() string { + return kanNames[k%KanMax] +} + +type Shi12 uint + +const ( + Rat Shi12 = iota // 子 + Ox // 丑 + Tiger // 寅 + Rabbit // 卯 + Dragon // 辰 + Snake // 巳 + Horse // 午 + Sheep // 未 + Monkey // 申 + Rooster // 酉 + Dog // 戌 + Boar // 亥 + ShiMax +) + +var shiNames = [ShiMax]string{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"} + +func (s Shi12) String() string { + return shiNames[s%ShiMax] +} + +var ( + JST = time.FixedZone("Asia/Tokyo", int((9 * time.Hour).Seconds())) // Japan Standard Time; 日本標準時 + baseDay = time.Date(2001, time.January, 1, 0, 0, 0, 0, JST) // 2001-01-01 is 甲子 + baseYear = 1984 // Year 1984 is 甲子 +) + +// ZodiacDayNumber function returns japanese zodiac day number from 2001-01-01. +func ZodiacDayNumber(t time.Time) (Kan10, Shi12) { + n := int64(t.Sub(baseDay).Hours()) / 24 + k := n % int64(KanMax) + if k < 0 { + k += int64(KanMax) + } + s := n % int64(ShiMax) + if s < 0 { + s += int64(ShiMax) + } + return Kan10(k), Shi12(s) +} + +// ZodiacYearNumber function returns japanese zodiac year number from 1984. +func ZodiacYearNumber(y int) (Kan10, Shi12) { + n := y - baseYear + k := n % int(KanMax) + if k < 0 { + k += int(KanMax) + } + s := n % int(ShiMax) + if s < 0 { + s += int(ShiMax) + } + return Kan10(k), Shi12(s) +} + +/* Copyright 2021 Spiegel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/zodiac/zodiac_test.go b/zodiac/zodiac_test.go new file mode 100644 index 0000000..a69b0bf --- /dev/null +++ b/zodiac/zodiac_test.go @@ -0,0 +1,111 @@ +package zodiac_test + +import ( + "testing" + "time" + + "github.com/goark/koyomi/zodiac" +) + +func TestKan10(t *testing.T) { + testCases := []struct { + kan zodiac.Kan10 + name string + }{ + {kan: zodiac.Kinoe, name: "甲"}, + {kan: zodiac.Kinoto, name: "乙"}, + {kan: zodiac.Hinoe, name: "丙"}, + {kan: zodiac.Hinoto, name: "丁"}, + {kan: zodiac.Tsutinoe, name: "戊"}, + {kan: zodiac.Tsutinoto, name: "己"}, + {kan: zodiac.Kanoe, name: "庚"}, + {kan: zodiac.Kanoto, name: "辛"}, + {kan: zodiac.Mizunoe, name: "壬"}, + {kan: zodiac.Mizunoto, name: "癸"}, + {kan: zodiac.Kan10(10), name: "甲"}, + } + + for _, tc := range testCases { + str := tc.kan.String() + if str != tc.name { + t.Errorf("zodiac.Kan10(%v) is \"%v\", want %v", uint(tc.kan), str, tc.name) + } + } +} + +func TestShi12(t *testing.T) { + testCases := []struct { + shi zodiac.Shi12 + name string + }{ + {shi: zodiac.Rat, name: "子"}, + {shi: zodiac.Ox, name: "丑"}, + {shi: zodiac.Tiger, name: "寅"}, + {shi: zodiac.Rabbit, name: "卯"}, + {shi: zodiac.Dragon, name: "辰"}, + {shi: zodiac.Snake, name: "巳"}, + {shi: zodiac.Horse, name: "午"}, + {shi: zodiac.Sheep, name: "未"}, + {shi: zodiac.Monkey, name: "申"}, + {shi: zodiac.Rooster, name: "酉"}, + {shi: zodiac.Dog, name: "戌"}, + {shi: zodiac.Boar, name: "亥"}, + {shi: zodiac.Shi12(12), name: "子"}, + } + + for _, tc := range testCases { + str := tc.shi.String() + if str != tc.name { + t.Errorf("zodiac.Shi12(%v) is \"%v\", want %v", uint(tc.shi), str, tc.name) + } + } +} + +func TestZodiac(t *testing.T) { + testCases := []struct { + t time.Time + kanYear zodiac.Kan10 + shiYear zodiac.Shi12 + kanDay zodiac.Kan10 + shiDay zodiac.Shi12 + }{ + {t: time.Date(1983, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Mizunoto, shiYear: zodiac.Boar, kanDay: zodiac.Tsutinoto, shiDay: zodiac.Ox}, + {t: time.Date(1984, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Kinoe, shiYear: zodiac.Rat, kanDay: zodiac.Kinoe, shiDay: zodiac.Horse}, + {t: time.Date(1985, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Kinoto, shiYear: zodiac.Ox, kanDay: zodiac.Kanoe, shiDay: zodiac.Rat}, + {t: time.Date(2000, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Kanoe, shiYear: zodiac.Dragon, kanDay: zodiac.Tsutinoe, shiDay: zodiac.Horse}, + {t: time.Date(2001, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Kanoto, shiYear: zodiac.Snake, kanDay: zodiac.Kinoe, shiDay: zodiac.Rat}, + {t: time.Date(2002, time.January, 1, 0, 0, 0, 0, zodiac.JST), kanYear: zodiac.Mizunoe, shiYear: zodiac.Horse, kanDay: zodiac.Tsutinoto, shiDay: zodiac.Snake}, + } + + for _, tc := range testCases { + kanYear, shiYear := zodiac.ZodiacYearNumber(tc.t.Year()) + if kanYear != tc.kanYear { + t.Errorf("result of ZodiacYearNumber(\"%v\") is \"%v\", want %v", tc.t, kanYear, tc.kanYear) + } + if shiYear != tc.shiYear { + t.Errorf("result of ZodiacYearNumber(\"%v\") is \"%v\", want %v", tc.t, shiYear, tc.shiYear) + } + kanDay, shiDay := zodiac.ZodiacDayNumber(tc.t) + if kanDay != tc.kanDay { + t.Errorf("result of ZodiacDayNumber(\"%v\") is \"%v\", want %v", tc.t, kanDay, tc.kanDay) + } + if shiYear != tc.shiYear { + t.Errorf("result of ZodiacDayNumber(\"%v\") is \"%v\", want %v", tc.t, shiDay, tc.shiDay) + } + } +} + +/* Copyright 2021 Spiegel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */