はじめに
はじめまして、@choujukuです。
食品工場向けSaaS KAMINASHIではサーバーサイドをgolangで書いており、データベース関連のライブラリとしてdbrを使っています。
dbrでjstを使うとき、特にDBにTime型の値をインサートするときの情報がググってもパッと出てこなかったので備忘録として記載します。
dbrで値を変換している箇所
dbr内のdialect/mysql.goでencodeしています。
以下のコードがgolangのTime型を変換している箇所です。
func (d mysql) EncodeTime(t time.Time) string {
return `'` + t.UTC().Format(timeFormat) + `'`
}
見事にUTCで変換しています。ここをJSTで変換するようにどうにかしたいわけです。
対応
今回はこんな感じで独自のstructを定義して対応しました。
db.go
func open(driver, dsn string, log dbr.EventReceiver) (*dbr.Connection, error) {
if log == nil {
log = &dbr.NullEventReceiver{}
}
conn, err := sql.Open(driver, dsn)
if err != nil {
return nil, err
}
d := mysqlExample{}
return &dbr.Connection{DB: conn, EventReceiver: log, Dialect: d}, nil
}
type mysqlExample struct{}
func (d mysqlExample) QuoteIdent(s string) string {
return quoteIdent(s, "`")
}
func (d mysqlExample) EncodeString(s string) string {
buf := new(bytes.Buffer)
buf.WriteRune('\'')
// https://dev.mysql.com/doc/refman/5.7/en/string-literals.html
for i := 0; i < len(s); i++ {
switch s[i] {
case 0:
buf.WriteString(`\0`)
case '\'':
buf.WriteString(`\'`)
case '"':
buf.WriteString(`\"`)
case '\b':
buf.WriteString(`\b`)
case '\n':
buf.WriteString(`\n`)
case '\r':
buf.WriteString(`\r`)
case '\t':
buf.WriteString(`\t`)
case 26:
buf.WriteString(`\Z`)
case '\\':
buf.WriteString(`\\`)
default:
buf.WriteByte(s[i])
}
}
buf.WriteRune('\'')
return buf.String()
}
func (d mysqlExample) EncodeBool(b bool) string {
if b {
return "1"
}
return "0"
}
func (d mysqlExample) EncodeTime(t time.Time) string {
return `'` + t.Format(timeFormat) + `'`
}
func (d mysqlExample) EncodeBytes(b []byte) string {
return fmt.Sprintf(`0x%x`, b)
}
func (d mysqlExample) Placeholder(_ int) string {
return "?"
}
const (
timeFormat = "2006-1-2 15:04:05.000000"
)
func quoteIdent(s, quote string) string {
part := strings.SplitN(s, ".", 2)
if len(part) == 2 {
return quoteIdent(part[0], quote) + "." + quoteIdent(part[1], quote)
}
return quote + s + quote
}
EncodeTime(t time.Time)
を独自のdialectを定義することで上書きするような動作にしています。
こう書くことで、アプリ内のTimeZoneが使われるので、UTC以外のTimeZoneを使うことができます。
終わりに
強引な感じですが、dbrでUTC以外を使いたい時の一つの手として紹介しました。
参考になれば幸いです。
また、KAMINASHIを開発しているユリシーズではエンジニア積極採用中です!