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

Commit

Permalink
Hack around truncation, add more tests including negative offset time…
Browse files Browse the repository at this point in the history
…zones
  • Loading branch information
lestrrat committed May 31, 2018
1 parent 7539c08 commit cb66a47
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 37 deletions.
24 changes: 20 additions & 4 deletions rotatelogs.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,26 @@ func New(p string, options ...Option) (*RotateLogs, error) {

func (rl *RotateLogs) genFilename() string {
now := rl.clock.Now()
_, offset := now.Zone()
base := now.Truncate(rl.rotationTime).Add(-1 * time.Duration(offset) * time.Second)
t := now.Add(base.Sub(now))
return rl.pattern.FormatString(t)

// XXX HACK: Truncate only happens in UTC semantics, apparently.
// observed values for truncating given time with 86400 secs:
//
// before truncation: 2018/06/01 03:54:54 2018-06-01T03:18:00+09:00
// after truncation: 2018/06/01 03:54:54 2018-05-31T09:00:00+09:00
//
// This is really annoying when we want to truncate in local time
// so we hack: we take the apparent local time in the local zone,
// and pretend that it's in UTC. do our math, and put it back to
// the local zone
var base time.Time
if now.Location() != time.UTC {
base = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond(), time.UTC)
base = base.Truncate(time.Duration(rl.rotationTime))
base = time.Date(base.Year(), base.Month(), base.Day(), base.Hour(), base.Minute(), base.Second(), base.Nanosecond(), base.Location())
} else {
base = now.Truncate(time.Duration(rl.rotationTime))
}
return rl.pattern.FormatString(base)
}

// Write satisfies the io.Writer interface. It writes to the
Expand Down
76 changes: 43 additions & 33 deletions rotatelogs_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rotatelogs_test

import (
"fmt"
"io"
"io/ioutil"
"log"
Expand All @@ -12,7 +13,6 @@ import (

"github.com/jonboulle/clockwork"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/lestrrat-go/strftime"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -360,45 +360,55 @@ func TestRotationGenerationalNames(t *testing.T) {
})
}

type ClockFunc func() time.Time

func (f ClockFunc) Now() time.Time {
return f()
}

func TestGHIssue23(t *testing.T) {
dir, err := ioutil.TempDir("", "file-rotatelogs-generational")
if !assert.NoError(t, err, `creating temporary directory should succeed`) {
return
}
defer os.RemoveAll(dir)

t.Run("Set location to Asia/Tokyo", func(t *testing.T) {
loc, _ := time.LoadLocation("Asia/Tokyo")
rl, err := rotatelogs.New(
filepath.Join(dir, "asia_tokyo.%Y%m%d%H%M.log"),
rotatelogs.WithLocation(loc),
)
if !assert.NoError(t, err, "rotatelogs.New should succeed") {
return
}

// Timing sensitive...

var now time.Time
for {
now = time.Now().In(loc)
if now.Hour() == 23 && now.Minute() >= 59 {
t.Logf("This test is sensitive to date changes. don't run this test after 23:59 Asia/Tokyo time")
time.Sleep(time.Minute)
continue
}
break
}
dt := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
expected, err := strftime.Format("asia_tokyo.%Y%m%d%H%M.log",dt)
if !assert.NoError(t, err, "strftime.Format should succeed") {
return
for _, locName := range []string{"Asia/Tokyo", "Pacific/Honolulu"} {
loc, _ := time.LoadLocation(locName)
tests := []struct {
Expected string
Clock rotatelogs.Clock
}{
{
Expected: filepath.Join(dir, strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".201806010000.log"),
Clock: ClockFunc(func() time.Time {
return time.Date(2018, 6, 1, 3, 18, 0, 0, loc)
}),
},
{
Expected: filepath.Join(dir, strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".201712310000.log"),
Clock: ClockFunc(func() time.Time {
return time.Date(2017, 12, 31, 23, 52, 0, 0, loc)
}),
},
}
expected = filepath.Join(dir, expected)

rl.Rotate()
if !assert.Equal(t, expected, rl.CurrentFileName(), "file names should match") {
return
for _, test := range tests {
t.Run(fmt.Sprintf("location = %s, time = %s", locName, test.Clock.Now().Format(time.RFC3339)), func(t *testing.T) {
template := strings.ToLower(strings.Replace(locName, "/", "_", -1)) + ".%Y%m%d%H%M.log"
rl, err := rotatelogs.New(
filepath.Join(dir, template),
rotatelogs.WithClock(test.Clock), // we're not using WithLocation, but it's the same thing
)
if !assert.NoError(t, err, "rotatelogs.New should succeed") {
return
}

t.Logf("expected %s", test.Expected)
rl.Rotate()
if !assert.Equal(t, test.Expected, rl.CurrentFileName(), "file names should match") {
return
}
})
}
})
}
}

0 comments on commit cb66a47

Please sign in to comment.