diff --git a/strftime/strftime.go b/strftime/strftime.go index f623fe1..f9f6af7 100644 --- a/strftime/strftime.go +++ b/strftime/strftime.go @@ -14,27 +14,33 @@ import ( "unsafe" ) +// Note: The use of errno below is not thread-safe. +// +// Even if we added a mutex, it would not be thread-safe +// relative to other C stdlib calls that don't use that mutex. +// +// OTOH, I can't find a format string that C strftime thinks is illegal +// to test this with, so maybe this is a non-issue + // Strftime wraps the C Strftime function func Strftime(format string, t time.Time) (string, error) { - _, off := t.Zone() - tz := t.Location() var ( - secs = t.Sub(time.Date(1970, 1, 1, 0, 0, 0, 0, tz)).Seconds() - float64(off) - tt = C.time_t(secs) - tm = C.struct_tm{} - cFormat = C.CString(format) - cOut [256]C.char + _, offset = t.Zone() + tz = t.Location() + secs = t.Sub(time.Date(1970, 1, 1, 0, 0, 0, 0, tz)).Seconds() - float64(offset) + tt = C.time_t(secs) + tm = C.struct_tm{} + cFormat = C.CString(format) + cOut [256]C.char ) defer C.free(unsafe.Pointer(cFormat)) // nolint: gas C.localtime_r(&tt, &tm) size := C.strftime(&cOut[0], C.size_t(len(cOut)), cFormat, &tm) - // This is not thread-safe. Even if we add a mutex, it is not thread-safe - // relative to other C stdlib calls that don't use it. - // OTOH, I can't find a format string that C strftime thinks is illegal, - // so maybe this is a non-issue if size == 0 { - errno := C.read_errno() - return "", syscall.Errno(errno) + // If size == 0 there *might* be an error. + if errno := C.read_errno(); errno != 0 { + return "", syscall.Errno(errno) + } } return C.GoString(&cOut[0]), nil } diff --git a/strftime/strftime_test.go b/strftime/strftime_test.go index 84f8b60..ff45fbd 100644 --- a/strftime/strftime_test.go +++ b/strftime/strftime_test.go @@ -42,6 +42,7 @@ func TestStrftime(t *testing.T) { {"%Y/%-m/%-d", "2006/1/2"}, {"%a, %b %d, %Y %z", "Mon, Jan 02, 2006 -0500"}, {"%a, %b %d, %Y %Z", "Mon, Jan 02, 2006 EST"}, + {"", ""}, } for _, test := range tests { s, err := Strftime(test.format, rt)