github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xtime/xtime_test.go (about)

     1  package xtime
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/Aoi-hosizora/ahlib/xtesting"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestSetXXX(t *testing.T) {
    11  	now := time.Date(2020, time.Month(9), 30, 23, 39, 18, 789, time.FixedZone("", 8*60*60))
    12  	zero := time.Time{}
    13  
    14  	for _, tc := range []struct {
    15  		giveFn1 func() time.Time
    16  		giveFn2 func()
    17  		want    string
    18  	}{
    19  		{nil, func() {}, "0001-01-01T00:00:00Z"},
    20  
    21  		{func() time.Time { return SetYear(zero, now.Year()) }, nil, "2020-01-01T00:00:00Z"},
    22  		{func() time.Time { return SetMonth(zero, int(now.Month())) }, nil, "0001-09-01T00:00:00Z"},
    23  		{func() time.Time { return SetDay(zero, now.Day()) }, nil, "0001-01-30T00:00:00Z"},
    24  		{func() time.Time { return SetHour(zero, now.Hour()) }, nil, "0001-01-01T23:00:00Z"},
    25  		{func() time.Time { return SetMinute(zero, now.Minute()) }, nil, "0001-01-01T00:39:00Z"},
    26  		{func() time.Time { return SetSecond(zero, now.Second()) }, nil, "0001-01-01T00:00:18Z"},
    27  		{func() time.Time { return SetMillisecond(zero, 123) }, nil, "0001-01-01T00:00:00.123Z"},
    28  		{func() time.Time { return SetMicrosecond(zero, 123456) }, nil, "0001-01-01T00:00:00.123456Z"},
    29  		{func() time.Time { return SetNanosecond(zero, 123456789) }, nil, "0001-01-01T00:00:00.123456789Z"},
    30  		{func() time.Time { return SetLocation(zero, now.Location()) }, nil, "0001-01-01T00:00:00+08:00"},
    31  
    32  		{nil, func() { zero = SetYear(zero, now.Year()) }, "2020-01-01T00:00:00Z"},
    33  		{nil, func() { zero = SetMonth(zero, int(now.Month())) }, "2020-09-01T00:00:00Z"},
    34  		{nil, func() { zero = SetDay(zero, now.Day()) }, "2020-09-30T00:00:00Z"},
    35  		{nil, func() { zero = SetHour(zero, now.Hour()) }, "2020-09-30T23:00:00Z"},
    36  		{nil, func() { zero = SetMinute(zero, now.Minute()) }, "2020-09-30T23:39:00Z"},
    37  		{nil, func() { zero = SetSecond(zero, now.Second()) }, "2020-09-30T23:39:18Z"},
    38  		{nil, func() { zero = SetMillisecond(zero, 123) }, "2020-09-30T23:39:18.123Z"},
    39  		{nil, func() { zero = SetMicrosecond(zero, 123456) }, "2020-09-30T23:39:18.123456Z"},
    40  		{nil, func() { zero = SetNanosecond(zero, now.Nanosecond()) }, "2020-09-30T23:39:18.000000789Z"},
    41  		{nil, func() { zero = SetLocation(zero, now.Location()) }, "2020-09-30T23:39:18.000000789+08:00"},
    42  	} {
    43  		if tc.giveFn1 != nil {
    44  			newTime := tc.giveFn1()
    45  			xtesting.Equal(t, newTime.Format(time.RFC3339Nano), tc.want)
    46  		} else {
    47  			tc.giveFn2()
    48  			xtesting.Equal(t, zero.Format(time.RFC3339Nano), tc.want)
    49  		}
    50  	}
    51  
    52  	xtesting.Equal(t, zero, now)
    53  }
    54  
    55  func TestToXXX(t *testing.T) {
    56  	now := time.Date(2020, time.Month(9), 30, 23, 39, 18, 789, time.FixedZone("test", 8*60*60))
    57  
    58  	for _, tc := range []struct {
    59  		giveFn   func() time.Time
    60  		wantTime time.Time
    61  	}{
    62  		{func() time.Time { return ToDate(now) },
    63  			time.Date(2020, time.Month(9), 30, 0, 0, 0, 0, time.FixedZone("", 8*60*60))},
    64  		{func() time.Time { return ToDateTime(now) },
    65  			time.Date(2020, time.Month(9), 30, 23, 39, 18, 0, time.FixedZone("", 8*60*60))},
    66  		{func() time.Time { return ToDateTimeNS(now) },
    67  			time.Date(2020, time.Month(9), 30, 23, 39, 18, 789, time.FixedZone("", 8*60*60))},
    68  	} {
    69  		newTime := tc.giveFn()
    70  		xtesting.Equal(t, newTime.Year(), tc.wantTime.Year())
    71  		xtesting.Equal(t, newTime.Month(), tc.wantTime.Month())
    72  		xtesting.Equal(t, newTime.Day(), tc.wantTime.Day())
    73  		xtesting.Equal(t, newTime.Hour(), tc.wantTime.Hour())
    74  		xtesting.Equal(t, newTime.Minute(), tc.wantTime.Minute())
    75  		xtesting.Equal(t, newTime.Second(), tc.wantTime.Second())
    76  		xtesting.Equal(t, newTime.Nanosecond(), tc.wantTime.Nanosecond())
    77  		xtesting.Equal(t, newTime.Location(), tc.wantTime.Location())
    78  	}
    79  }
    80  
    81  func TestLocationDurationAndGetTimeLocation(t *testing.T) {
    82  	t1, _ := time.Parse(time.RFC3339, "2020-09-30T23:56:52Z")      // UTC
    83  	t2, _ := time.Parse(time.RFC3339, "2020-09-30T23:56:52-07:00") // ""
    84  	t3, _ := time.Parse(CJKDateTime, "2020-09-30 23:56:52")        // UTC
    85  	t4, _ := time.Parse(time.RFC3339, "2020-09-30T23:56:52+08:00") // Local
    86  	t5, _ := time.Parse(time.RFC3339, "2020-09-30T23:56:52+09:00") // ""
    87  	t6, _ := time.Parse(time.RFC3339, "2020-09-30T23:56:52-12:30") // ""
    88  
    89  	for _, tc := range []struct {
    90  		giveTime     time.Time
    91  		wantDuration int
    92  	}{
    93  		{t1, 0},                // +00:00
    94  		{t2, -7 * 3600},        // -07:00
    95  		{t3, 0},                // +00:00
    96  		{t4, 8 * 3600},         // +08:00
    97  		{t5, 9 * 3600},         // +09:00
    98  		{t6, -12*3600 - 30*60}, // -12:30
    99  	} {
   100  		duration := LocationDuration(tc.giveTime.Location())
   101  		xtesting.Equal(t, int(duration.Seconds()), tc.wantDuration)
   102  
   103  		newLocation := GetTimeLocation(tc.giveTime)
   104  		xtesting.Equal(t, newLocation.String(), "")
   105  		newDuration := LocationDuration(newLocation)
   106  		xtesting.Equal(t, int(newDuration.Seconds()), tc.wantDuration)
   107  	}
   108  
   109  	loc := GetLocalLocation()
   110  	xtesting.Equal(t, loc.String(), "")
   111  	xtesting.Equal(t, loc, time.FixedZone("", int(LocationDuration(time.Local).Seconds())))
   112  }
   113  
   114  func TestParseTimezone(t *testing.T) {
   115  	for _, tc := range []struct {
   116  		give string
   117  		want *time.Location
   118  	}{
   119  		{"", nil},
   120  		{"0", nil},
   121  		{"09", nil},
   122  		{"09:00", nil},
   123  		{"+", nil},
   124  		{"+0", time.FixedZone("UTC+00:00", 0)}, // +X
   125  		{"+09", time.FixedZone("UTC+09:00", 9*3600)}, // +XX
   126  		{"+009", nil},
   127  		{"+09:", nil},
   128  		{"-09", time.FixedZone("UTC-09:00", -9*3600)},          // -XX
   129  		{"-9:0", time.FixedZone("UTC-09:00", -9*3600)},         // -X:X
   130  		{"-9:00", time.FixedZone("UTC-09:00", -9*3600)},        // -X:XX
   131  		{"-09:0", time.FixedZone("UTC-09:00", -9*3600)},        // -XX:X
   132  		{"-09:30", time.FixedZone("UTC-09:30", -9*3600-30*60)}, // -XX:XX
   133  		{"-09:300", nil},
   134  	} {
   135  		if tc.want == nil {
   136  			_, err := ParseTimezone(tc.give)
   137  			xtesting.NotNil(t, err)
   138  		} else {
   139  			loc, err := ParseTimezone(tc.give)
   140  			xtesting.Equal(t, loc, tc.want)
   141  			xtesting.Nil(t, err)
   142  		}
   143  	}
   144  }
   145  
   146  func TestTruncateTime(t *testing.T) {
   147  	for _, loc := range []*time.Location{
   148  		time.UTC,
   149  		time.FixedZone("", 8*60*60),
   150  		time.FixedZone("", -9*60*60),
   151  		time.FixedZone("", -2*30*60),
   152  	} {
   153  		d1 := time.Date(2021, 12, 27, 23, 49, 57, 123456789, loc)
   154  		d2 := time.Date(2018, 5, 1, 3, 4, 6, 999000000, loc)
   155  		for _, tc := range []struct {
   156  			giveTime     time.Time
   157  			giveDuration time.Duration
   158  			want         time.Time
   159  		}{
   160  			{d1, time.Nanosecond, time.Date(2021, 12, 27, 23, 49, 57, 123456789, loc)},
   161  			{d1, time.Microsecond, time.Date(2021, 12, 27, 23, 49, 57, 123456000, loc)},
   162  			{d1, time.Millisecond, time.Date(2021, 12, 27, 23, 49, 57, 123000000, loc)},
   163  			{d1, time.Millisecond * 10, time.Date(2021, 12, 27, 23, 49, 57, 120000000, loc)},
   164  			{d1, time.Second, time.Date(2021, 12, 27, 23, 49, 57, 0, loc)},
   165  			{d1, time.Second * 2, time.Date(2021, 12, 27, 23, 49, 56, 0, loc)},
   166  			{d1, time.Second * 5, time.Date(2021, 12, 27, 23, 49, 55, 0, loc)},
   167  			{d1, time.Second * 10, time.Date(2021, 12, 27, 23, 49, 50, 0, loc)},
   168  			{d1, time.Second * 20, time.Date(2021, 12, 27, 23, 49, 40, 0, loc)},
   169  			{d1, time.Minute, time.Date(2021, 12, 27, 23, 49, 0, 0, loc)},
   170  			{d1, time.Minute * 2, time.Date(2021, 12, 27, 23, 48, 0, 0, loc)},
   171  			{d1, time.Minute * 5, time.Date(2021, 12, 27, 23, 45, 0, 0, loc)},
   172  			{d1, time.Minute * 10, time.Date(2021, 12, 27, 23, 40, 0, 0, loc)},
   173  			{d1, time.Minute * 20, time.Date(2021, 12, 27, 23, 40, 0, 0, loc)},
   174  			//
   175  			{d2, time.Millisecond, time.Date(2018, 5, 1, 3, 4, 6, 999000000, loc)},
   176  			{d2, time.Millisecond * 10, time.Date(2018, 5, 1, 3, 4, 6, 990000000, loc)},
   177  			{d2, time.Second, time.Date(2018, 5, 1, 3, 4, 6, 0, loc)},
   178  			{d2, time.Second * 2, time.Date(2018, 5, 1, 3, 4, 6, 0, loc)},
   179  			{d2, time.Second * 20, time.Date(2018, 5, 1, 3, 4, 0, 0, loc)},
   180  			{d2, time.Minute, time.Date(2018, 5, 1, 3, 4, 0, 0, loc)},
   181  			{d2, time.Minute * 2, time.Date(2018, 5, 1, 3, 4, 0, 0, loc)},
   182  			{d2, time.Minute * 20, time.Date(2018, 5, 1, 3, 0, 0, 0, loc)},
   183  			//
   184  			{d1, time.Hour, time.Date(2021, 12, 27, 23, 0, 0, 0, loc)},
   185  			{d1, time.Hour * 2, time.Date(2021, 12, 27, 22, 0, 0, 0, loc)},
   186  			{d1, time.Hour * 3, time.Date(2021, 12, 27, 21, 0, 0, 0, loc)},
   187  			{d1, time.Hour * 24, time.Date(2021, 12, 27, 0, 0, 0, 0, loc)},
   188  			{d1, time.Hour * 24 * 2, time.Date(2021, 12, 27, 0, 0, 0, 0, loc)},
   189  			{d1, time.Hour * 24 * 3, time.Date(2021, 12, 27, 0, 0, 0, 0, loc)},
   190  			//
   191  			{d2, time.Hour, time.Date(2018, 5, 1, 3, 0, 0, 0, loc)},
   192  			{d2, time.Hour * 2, time.Date(2018, 5, 1, 2, 0, 0, 0, loc)},
   193  			{d2, time.Hour * 3, time.Date(2018, 5, 1, 3, 0, 0, 0, loc)},
   194  			{d2, time.Hour * 24, time.Date(2018, 5, 1, 0, 0, 0, 0, loc)},
   195  			{d2, time.Hour * 24 * 2, time.Date(2018, 5, 1, 0, 0, 0, 0, loc)},
   196  			{d2, time.Hour * 24 * 3, time.Date(2018, 4, 29, 0, 0, 0, 0, loc)},
   197  		} {
   198  			t.Run(fmt.Sprintf("%s_%s_%s", tc.giveTime.Format("20060102"), tc.giveDuration, LocationDuration(loc)), func(t *testing.T) {
   199  				xtesting.Equal(t, TruncateTime(tc.giveTime, tc.giveDuration), tc.want)
   200  			})
   201  		}
   202  	}
   203  }
   204  
   205  func TestDurationComponent(t *testing.T) {
   206  	duration1 := 5*24*time.Hour + 5*time.Hour + 32*time.Minute + 24*time.Second + 123*time.Millisecond + 456*time.Microsecond + 789*time.Nanosecond
   207  	duration2 := 105 * 24 * time.Hour
   208  	duration3 := 24*time.Hour + 30*time.Minute + 1*time.Microsecond
   209  	duration4 := 5*time.Hour + 30*time.Minute + 1*time.Microsecond
   210  	duration5 := 0 * time.Second
   211  
   212  	for _, tc := range []struct {
   213  		give       time.Duration
   214  		wantDay    int
   215  		wantHour   int
   216  		wantMinute int
   217  		wantSecond int
   218  		wantMs     int
   219  		wantUs     int
   220  		wantNs     int
   221  	}{
   222  		{duration1, 5, 5, 32, 24, 123, 456, 789},
   223  		{duration2, 105, 0, 0, 0, 0, 0, 0},
   224  		{duration3, 1, 0, 30, 0, 0, 1, 0},
   225  		{duration4, 0, 5, 30, 0, 0, 1, 0},
   226  		{duration5, 0, 0, 0, 0, 0, 0, 0},
   227  	} {
   228  		xtesting.Equal(t, DurationDayComponent(tc.give), tc.wantDay)
   229  		xtesting.Equal(t, DurationHourComponent(tc.give), tc.wantHour)
   230  		xtesting.Equal(t, DurationMinuteComponent(tc.give), tc.wantMinute)
   231  		xtesting.Equal(t, DurationSecondComponent(tc.give), tc.wantSecond)
   232  		xtesting.Equal(t, DurationMillisecondComponent(tc.give), tc.wantMs)
   233  		xtesting.Equal(t, DurationMicrosecondComponent(tc.give), tc.wantUs)
   234  		xtesting.Equal(t, DurationNanosecondComponent(tc.give), tc.wantNs)
   235  	}
   236  }
   237  
   238  func TestDurationTotal(t *testing.T) {
   239  	duration1 := 5*24*time.Hour + 5*time.Hour + 32*time.Minute + 24*time.Second + 123*time.Millisecond + 456*time.Microsecond + 789*time.Nanosecond
   240  	duration2 := 105 * 24 * time.Hour
   241  	duration3 := 24*time.Hour + 30*time.Minute + 1*time.Microsecond
   242  	duration4 := 5*time.Hour + 30*time.Minute + 1*time.Microsecond
   243  	duration5 := 0 * time.Second
   244  
   245  	for _, tc := range []struct {
   246  		give       time.Duration
   247  		wantDay    float64
   248  		wantHour   float64
   249  		wantMinute float64
   250  		wantSecond float64
   251  		wantMs     int64
   252  		wantUs     int64
   253  		wantNs     int64
   254  	}{
   255  		{duration1, 5.2308, 125.5400, 7532.4020, 451944.123456789, 451944123, 451944123456, 451944123456789},
   256  		{duration2, 105, 2520, 151200, 9072000, 9072000000, 9072000000000, 9072000000000000},
   257  		{duration3, 1.0208, 24.5, 1470., 88200., 88200000, 88200000001, 88200000001000},
   258  		{duration4, 0.2292, 5.5, 330., 19800, 19800000, 19800000001, 19800000001000},
   259  		{duration5, 0, 0, 0, 0, 0, 0, 0},
   260  	} {
   261  		xtesting.Equal(t, DurationTotalNanoseconds(tc.give), tc.wantNs)
   262  		xtesting.Equal(t, DurationTotalMicroseconds(tc.give), tc.wantUs)
   263  		xtesting.Equal(t, DurationTotalMilliseconds(tc.give), tc.wantMs)
   264  		xtesting.InDelta(t, DurationTotalSeconds(tc.give), tc.wantSecond, 1e-3)
   265  		xtesting.InDelta(t, DurationTotalMinutes(tc.give), tc.wantMinute, 1e-3)
   266  		xtesting.InDelta(t, DurationTotalHours(tc.give), tc.wantHour, 1e-3)
   267  		xtesting.InDelta(t, DurationTotalDays(tc.give), tc.wantDay, 1e-3)
   268  	}
   269  }
   270  
   271  func TestClock(t *testing.T) {
   272  	xtesting.Equal(t, LocationDuration(UTC.Now().Location()), time.Duration(0))
   273  	xtesting.Equal(t, LocationDuration(Local.Now().Location()), LocationDuration(time.Local))
   274  	now := time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60))
   275  	pNow := &now
   276  	clock := CustomClock(pNow)
   277  	xtesting.Equal(t, clock.Now(), time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", 8*60*60)))
   278  	*pNow = SetLocation(now, time.FixedZone("", -9*60*60))
   279  	xtesting.Equal(t, clock.Now(), time.Date(2001, 1, 1, 0, 0, 0, 0, time.FixedZone("", -9*60*60)))
   280  	*pNow = SetYear(now, 2021)
   281  	*pNow = SetMonth(now, 12)
   282  	*pNow = SetDay(now, 30)
   283  	*pNow = SetLocation(now, time.UTC)
   284  	xtesting.Equal(t, clock.Now(), time.Date(2021, 12, 30, 0, 0, 0, 0, time.UTC))
   285  }