🏖️

golangで祝日判定と営業日計算できるライブラリを作った

2017/10/13に公開

はじめに

自分がGoでプログラムを組んでいたら営業日計算が必要な場合に遭遇しました。
基本的な営業日なので土日祝日を除いた日での計算になります。
そこまで複雑ではないしrubyならそれっぽいgemがあったはずだからGoでもあるだろうと探してもなかなか見つからない...
外部APIを使用するとメンテコストが高いだろうと思いライブラリとして作りました。

リポジトリ

https://github.com/yut-kt/goholiday

Install

$ go get github.com/yut-kt/goholiday

Sample

package main

import (
	"fmt"
	"github.com/yut-kt/goholiday" // ライブラリインポート
	"github.com/yut-kt/goholiday/nholidays/jp"
	"time"
)

func main() {
	ghj := goholiday.New(jp.New())

	NYD := "2018-01-01 JST"
	datetime, err := time.Parse("2006-01-02 MST", NYD)
	if err != nil {
		panic(err)
	}

	// 20営業日後を計算
	fmt.Println(ghj.BusinessDaysAfter(datetime, 20))

	// 20営業日前を計算
	fmt.Println(ghj.BusinessDaysBefore(datetime, 20))

	// 祝日かどうか判定
	fmt.Println(ghj.IsNationalHoliday(datetime))

	// 営業日かどうか判定
	fmt.Println(ghj.IsBusinessDay(datetime))
}

今回はパフォーマンスよりも安定性を意識して作ったので少し遅く感じるかもしれませんが、そこまで時間がかかるわけでもないので計算が面倒と感じたら使えるレベルかなと思います。

事前に祝日をメモリ展開することでパフォーマンスも改善しています。

ベンチマーク

ベンチマーク載せておきます。

判定は0.0002ms,営業日計算は0.002sほどかかっています.
バージョンアップして当初から数百倍の速度にはしてあるので実用できそうかと思います.

goos: darwin
goarch: amd64
pkg: github.com/yut-kt/goholiday
BenchmarkIsNationalHoliday-4    	10000000	       222 ns/op	      16 B/op	       1 allocs/op
BenchmarkIsNationalHoliday-4    	10000000	       233 ns/op	      16 B/op	       1 allocs/op
BenchmarkIsNationalHoliday-4    	10000000	       235 ns/op	      16 B/op	       1 allocs/op
BenchmarkIsNationalHoliday-4    	10000000	       224 ns/op	      16 B/op	       1 allocs/op
BenchmarkIsNationalHoliday-4    	10000000	       226 ns/op	      16 B/op	       1 allocs/op
BenchmarkIsWeekDay-4            	10000000	       199 ns/op	      11 B/op	       0 allocs/op
BenchmarkIsWeekDay-4            	10000000	       200 ns/op	      11 B/op	       0 allocs/op
BenchmarkIsWeekDay-4            	10000000	       200 ns/op	      11 B/op	       0 allocs/op
BenchmarkIsWeekDay-4            	10000000	       185 ns/op	      11 B/op	       0 allocs/op
BenchmarkIsWeekDay-4            	10000000	       192 ns/op	      11 B/op	       0 allocs/op
BenchmarkBusinessDaysBefore-4   	   10000	   2368289 ns/op	   83723 B/op	    5225 allocs/op
BenchmarkBusinessDaysBefore-4   	   10000	   2153245 ns/op	   83723 B/op	    5225 allocs/op
BenchmarkBusinessDaysBefore-4   	   10000	   2122294 ns/op	   83723 B/op	    5225 allocs/op
BenchmarkBusinessDaysBefore-4   	   10000	   2179232 ns/op	   83723 B/op	    5225 allocs/op
BenchmarkBusinessDaysBefore-4   	   10000	   2091056 ns/op	   83723 B/op	    5225 allocs/op
BenchmarkBusinessDaysAfter-4    	   10000	   2033209 ns/op	   80509 B/op	    5024 allocs/op
BenchmarkBusinessDaysAfter-4    	   10000	   1923448 ns/op	   80509 B/op	    5024 allocs/op
BenchmarkBusinessDaysAfter-4    	   10000	   1973427 ns/op	   80509 B/op	    5024 allocs/op
BenchmarkBusinessDaysAfter-4    	   10000	   2109766 ns/op	   80509 B/op	    5024 allocs/op
BenchmarkBusinessDaysAfter-4    	   10000	   1909945 ns/op	   80509 B/op	    5024 allocs/op
PASS
ok  	github.com/yut-kt/goholiday	244.707s

さらにベンチマーク改善しました

$ go test -bench . -benchmem -count 5 -run none
goos: darwin
goarch: arm64
pkg: github.com/yut-kt/goholiday
BenchmarkNew-12                                    79984             13085 ns/op           42375 B/op          7 allocs/op
BenchmarkNew-12                                    93198             13324 ns/op           42375 B/op          7 allocs/op
BenchmarkNew-12                                    93420             13415 ns/op           42375 B/op          7 allocs/op
BenchmarkNew-12                                    85468             13360 ns/op           42375 B/op          7 allocs/op
BenchmarkNew-12                                    89742             13285 ns/op           42376 B/op          7 allocs/op
BenchmarkGoholiday_IsNationalHoliday-12            42303             29020 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_IsNationalHoliday-12            41546             28491 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_IsNationalHoliday-12            41554             28864 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_IsNationalHoliday-12            41583             28882 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_IsNationalHoliday-12            41703             28985 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_IsHoliday-12                    30775             39136 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsHoliday-12                    30190             39374 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsHoliday-12                    30613             39318 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsHoliday-12                    30726             40038 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsHoliday-12                    30562             40115 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsBusinessDay-12                29947             39978 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsBusinessDay-12                30261             39579 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsBusinessDay-12                30164             39439 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsBusinessDay-12                29936             40088 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_IsBusinessDay-12                29887             39679 ns/op            8128 B/op        508 allocs/op
BenchmarkGoholiday_SetUniqueHolidays-12            41427             28403 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_SetUniqueHolidays-12            41937             29126 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_SetUniqueHolidays-12            41332             28998 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_SetUniqueHolidays-12            42133             28862 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_SetUniqueHolidays-12            41314             29365 ns/op            5856 B/op        366 allocs/op
BenchmarkGoholiday_BusinessDaysAfter-12            19584             61063 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysAfter-12            19690             61339 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysAfter-12            19684             61210 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysAfter-12            19171             61532 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysAfter-12            19692             60958 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysBefore-12           19203             61553 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysBefore-12           19454             62000 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysBefore-12           19081             62520 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysBefore-12           19138             62519 ns/op           12048 B/op        753 allocs/op
BenchmarkGoholiday_BusinessDaysBefore-12           19383             62537 ns/op           12048 B/op        753 allocs/op
PASS
ok      github.com/yut-kt/goholiday     56.333s

おわりに

Go書いているのは楽しいけど結構他の言語だとこうできるのに、このライブラリないの!?みたいなことに陥るのでもっと言語自体もコミュニティも伸びて行って欲しいです。
現在はコミュニティも大きくなりましたが、ライブラリはまだ少なく感じますね。
もっとこんな機能があったら便利とかあればコメントいただけると追加や修正ができるかもしれないのでお願いします。

Discussion