Go言語のos.Chtimesで設定可能な最大日時は 2262-04-11 23:47:16.854775807 +0000 UTC

os.Chtimes のソース

を見ると、引数は time.Time なのですが、 syscall.Timespec に変換するときに timeUnixNano() を使っています。 UnixNano() は 1970-01-01T00:00:00Z からの通算ミリ秒です。

UnixNano() で int64 の最大値を設定したときと、 time.Time で表現可能な最大の日時を調べてみました。

https://play.golang.org/p/eUj5L-eEkS

package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    fmt.Println(time.Unix(int64(math.MaxInt64)/1e9, int64(math.MaxInt64)%1e9).UTC())
    fmt.Println(time.Unix(math.MaxInt64, 1e9-1).UTC())
}
2262-04-11 23:47:16.854775807 +0000 UTC
219250468-12-04 15:30:07.999999999 +0000 UTC

となりました。

Linux amd64 環境だと NsecToTimespecTimespec

func NsecToTimespec(nsec int64) (ts Timespec) {
    ts.Sec = nsec / 1e9
    ts.Nsec = nsec % 1e9
    return
}
type Timespec struct {
    Sec  int64
    Nsec int64
}

となっているので、 NsecToTimespec を使わずに

func Chtimes(name string, atime time.Time, mtime time.Time) error {
    var utimes [2]syscall.Timespec
    utimes[0] = syscall.Timespec(atime.Unix(), atime.Nanosecond())
    utimes[1] = syscall.Timespec(mtime.Unix(), mtime.Nanosecond())
    if e := syscall.UtimesNano(name, utimes[0:]); e != nil {
        return &PathError{"chtimes", name, e}
    }
    return nil
}

と書けば time.Time の限界まで渡すことは出来ます。とは言え syscall.UtimesNano が対応しているかはまた別問題ですが。

2262 年まで表現できれば個人的には困らないので、メモだけ残しておくということで。