Skip to content
This repository was archived by the owner on Jul 19, 2021. It is now read-only.

Commit 3b4f34a

Browse files
authored
Merge pull request #24 from lestrrat-go/topic/gh-23
Calculate t using time zone offsets
2 parents 81893a5 + cb66a47 commit 3b4f34a

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

rotatelogs.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,26 @@ func New(p string, options ...Option) (*RotateLogs, error) {
8484

8585
func (rl *RotateLogs) genFilename() string {
8686
now := rl.clock.Now()
87-
diff := time.Duration(now.UnixNano()) % rl.rotationTime
88-
t := now.Add(time.Duration(-1 * diff))
89-
return rl.pattern.FormatString(t)
87+
88+
// XXX HACK: Truncate only happens in UTC semantics, apparently.
89+
// observed values for truncating given time with 86400 secs:
90+
//
91+
// before truncation: 2018/06/01 03:54:54 2018-06-01T03:18:00+09:00
92+
// after truncation: 2018/06/01 03:54:54 2018-05-31T09:00:00+09:00
93+
//
94+
// This is really annoying when we want to truncate in local time
95+
// so we hack: we take the apparent local time in the local zone,
96+
// and pretend that it's in UTC. do our math, and put it back to
97+
// the local zone
98+
var base time.Time
99+
if now.Location() != time.UTC {
100+
base = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), time.UTC)
101+
base = base.Truncate(time.Duration(rl.rotationTime))
102+
base = time.Date(base.Year(), base.Month(), base.Day(), base.Hour(), base.Minute(), base.Second(), base.Nanosecond(), base.Location())
103+
} else {
104+
base = now.Truncate(time.Duration(rl.rotationTime))
105+
}
106+
return rl.pattern.FormatString(base)
90107
}
91108

92109
// Write satisfies the io.Writer interface. It writes to the

rotatelogs_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package rotatelogs_test
22

33
import (
4+
"fmt"
45
"io"
56
"io/ioutil"
67
"log"
@@ -358,3 +359,56 @@ func TestRotationGenerationalNames(t *testing.T) {
358359
defer rl.Close()
359360
})
360361
}
362+
363+
type ClockFunc func() time.Time
364+
365+
func (f ClockFunc) Now() time.Time {
366+
return f()
367+
}
368+
369+
func TestGHIssue23(t *testing.T) {
370+
dir, err := ioutil.TempDir("", "file-rotatelogs-generational")
371+
if !assert.NoError(t, err, `creating temporary directory should succeed`) {
372+
return
373+
}
374+
defer os.RemoveAll(dir)
375+
376+
for _, locName := range []string{"Asia/Tokyo", "Pacific/Honolulu"} {
377+
loc, _ := time.LoadLocation(locName)
378+
tests := []struct {
379+
Expected string
380+
Clock rotatelogs.Clock
381+
}{
382+
{
383+
Expected: filepath.Join(dir, strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".201806010000.log"),
384+
Clock: ClockFunc(func() time.Time {
385+
return time.Date(2018, 6, 1, 3, 18, 0, 0, loc)
386+
}),
387+
},
388+
{
389+
Expected: filepath.Join(dir, strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".201712310000.log"),
390+
Clock: ClockFunc(func() time.Time {
391+
return time.Date(2017, 12, 31, 23, 52, 0, 0, loc)
392+
}),
393+
},
394+
}
395+
for _, test := range tests {
396+
t.Run(fmt.Sprintf("location = %s, time = %s", locName, test.Clock.Now().Format(time.RFC3339)), func(t *testing.T) {
397+
template := strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".%Y%m%d%H%M.log"
398+
rl, err := rotatelogs.New(
399+
filepath.Join(dir, template),
400+
rotatelogs.WithClock(test.Clock), // we're not using WithLocation, but it's the same thing
401+
)
402+
if !assert.NoError(t, err, "rotatelogs.New should succeed") {
403+
return
404+
}
405+
406+
t.Logf("expected %s", test.Expected)
407+
rl.Rotate()
408+
if !assert.Equal(t, test.Expected, rl.CurrentFileName(), "file names should match") {
409+
return
410+
}
411+
})
412+
}
413+
}
414+
}

0 commit comments

Comments
 (0)