326 lines
8.1 KiB
Go
326 lines
8.1 KiB
Go
package timeutil
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTimeutil_StartOfPreviousMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2019, 12, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 15, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2019, 12, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 3, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := StartOfPreviousMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("start of month before %v is %v, got %v", tc.Input, tc.Expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_StartOfMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 1, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 2, 28, 1, 2, 3, 4, time.UTC),
|
|
Expected: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := StartOfMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("start of %v is %v, expected %v", tc.Input, result, tc.Expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsMonthStart(t *testing.T) {
|
|
testCases := []struct {
|
|
input time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
input: time.Date(2020, 1, 1, 0, 0, 0, 1, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: time.Date(2020, 4, 5, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsMonthStart(tc.input)
|
|
if result != tc.expected {
|
|
t.Errorf("is %v the start of the month? expected %t, got %t", tc.input, tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_EndOfMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
// The current behavior does not use the nanoseconds
|
|
// because we didn't want to clutter the result of end-of-month reporting.
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 15, 1, 2, 3, 4, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
// Leap year
|
|
Input: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 2, 29, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
// non-leap year
|
|
Input: time.Date(2100, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2100, 2, 28, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := EndOfMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("end of %v is %v, expected %v", tc.Input, result, tc.Expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsPreviousMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
tInput time.Time
|
|
compareInput time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
tInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 31, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
tInput: time.Date(2019, 12, 31, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 31, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
// leap year (false)
|
|
tInput: time.Date(2019, 12, 29, 10, 10, 10, 0, time.UTC),
|
|
compareInput: time.Date(2020, 2, 29, 10, 10, 10, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
// leap year (true)
|
|
tInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 2, 29, 10, 10, 10, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
tInput: time.Date(2018, 5, 5, 5, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
// test normalization. want to make subtracting 1 month from 3/30/2020 doesn't yield 2/30/2020, normalized
|
|
// to 3/1/2020
|
|
tInput: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 3, 30, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsPreviousMonth(tc.tInput, tc.compareInput)
|
|
if result != tc.expected {
|
|
t.Errorf("%v in previous month to %v? expected %t, got %t", tc.tInput, tc.compareInput, tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsCurrentMonth(t *testing.T) {
|
|
now := time.Now()
|
|
testCases := []struct {
|
|
input time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
input: now,
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfMonth(now).AddDate(0, 0, -1),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: EndOfMonth(now).AddDate(0, 0, -1),
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfMonth(now).AddDate(-1, 0, 0),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsCurrentMonth(tc.input, now)
|
|
if result != tc.expected {
|
|
t.Errorf("invalid result. expected %t for %v", tc.expected, tc.input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeUtil_ContiguousMonths(t *testing.T) {
|
|
testCases := []struct {
|
|
input []time.Time
|
|
expected []time.Time
|
|
}{
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 5, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{},
|
|
expected: []time.Time{},
|
|
},
|
|
{
|
|
input: nil,
|
|
expected: nil,
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 2, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 15, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 2, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := GetMostRecentContiguousMonths(tc.input)
|
|
|
|
if !reflect.DeepEqual(tc.expected, result) {
|
|
t.Errorf("invalid contiguous segment returned. expected %v, got %v", tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeUtil_ParseTimeFromPath(t *testing.T) {
|
|
testCases := []struct {
|
|
input string
|
|
expectedOut time.Time
|
|
expectError bool
|
|
}{
|
|
{
|
|
input: "719020800/1",
|
|
expectedOut: time.Unix(719020800, 0).UTC(),
|
|
expectError: false,
|
|
},
|
|
{
|
|
input: "1601415205/3",
|
|
expectedOut: time.Unix(1601415205, 0).UTC(),
|
|
expectError: false,
|
|
},
|
|
{
|
|
input: "baddata/3",
|
|
expectedOut: time.Time{},
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result, err := ParseTimeFromPath(tc.input)
|
|
gotError := err != nil
|
|
|
|
if result != tc.expectedOut {
|
|
t.Errorf("bad timestamp on input %q. expected: %v got: %v", tc.input, tc.expectedOut, result)
|
|
}
|
|
if gotError != tc.expectError {
|
|
t.Errorf("bad error status on input %q. expected error: %t, got error: %t", tc.input, tc.expectError, gotError)
|
|
}
|
|
}
|
|
}
|