github.com/viant/toolbox@v0.34.5/time_helper_test.go (about)

     1  package toolbox
     2  
     3  import (
     4  	"github.com/stretchr/testify/assert"
     5  	"math"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestAtTime_Next(t *testing.T) {
    11  
    12  	timeLayout := "2006-01-02 15:04:05"
    13  
    14  	var useCases = []struct {
    15  		description string
    16  		at          *AtTime
    17  		baseTime    string
    18  		expectTime  string
    19  	}{
    20  
    21  		{
    22  			description: "evey 1/2 - next day",
    23  			at: &AtTime{
    24  				WeekDay: "*",
    25  				Hour:    "*",
    26  				Minute:  "30",
    27  			},
    28  			baseTime:   "2019-01-01 23:33:01",
    29  			expectTime: "2019-01-02 01:30:00",
    30  		},
    31  
    32  		{
    33  			description: "evey 1/2, last minute - next day",
    34  			at: &AtTime{
    35  				WeekDay: "*",
    36  				Hour:    "*",
    37  				Minute:  "0,30",
    38  			},
    39  			baseTime:   "2019-01-01 23:59:00",
    40  			expectTime: "2019-01-02 01:00:00",
    41  		},
    42  
    43  		{
    44  			description: "evey 1/2, last day of the month - next day",
    45  			at: &AtTime{
    46  				WeekDay: "*",
    47  				Hour:    "*",
    48  				Minute:  "0,30",
    49  			},
    50  			baseTime:   "2019-05-31 23:59:00",
    51  			expectTime: "2019-06-01 01:00:00",
    52  		},
    53  
    54  		{
    55  			description: "evey hour - next day",
    56  			at: &AtTime{
    57  				WeekDay: "*",
    58  				Hour:    "0",
    59  				Minute:  "*",
    60  			},
    61  			baseTime:   "2019-01-01 23:01:01",
    62  			expectTime: "2019-01-02 00:02:00",
    63  		},
    64  
    65  		{
    66  			description: "evey minute",
    67  			at: &AtTime{
    68  				WeekDay: "*",
    69  				Hour:    "*",
    70  				Minute:  "*",
    71  			},
    72  			baseTime:   "2019-01-01 01:01:01",
    73  			expectTime: "2019-01-01 01:02:00",
    74  		},
    75  
    76  		{
    77  			description: "evey 30 minute before",
    78  			at: &AtTime{
    79  				WeekDay: "*",
    80  				Hour:    "*",
    81  				Minute:  "30",
    82  			},
    83  			baseTime:   "2019-01-01 01:01:01",
    84  			expectTime: "2019-01-01 01:30:00",
    85  		},
    86  		{
    87  			description: "evey 30 minute after",
    88  			at: &AtTime{
    89  				WeekDay: "*",
    90  				Hour:    "*",
    91  				Minute:  "30",
    92  			},
    93  			baseTime:   "2019-01-01 01:31:01",
    94  			expectTime: "2019-01-01 02:30:00",
    95  		},
    96  		{
    97  			description: "evey 10, 30 minute, before",
    98  			at: &AtTime{
    99  				WeekDay: "*",
   100  				Hour:    "*",
   101  				Minute:  "10,30",
   102  			},
   103  			baseTime:   "2019-01-01 01:09:01",
   104  			expectTime: "2019-01-01 01:10:00",
   105  		},
   106  		{
   107  			description: "evey 10, 30 minute, after first",
   108  			at: &AtTime{
   109  				WeekDay: "*",
   110  				Hour:    "*",
   111  				Minute:  "10,30",
   112  			},
   113  			baseTime:   "2019-01-01 01:13:01",
   114  			expectTime: "2019-01-01 01:30:00",
   115  		},
   116  		{
   117  			description: "evey 10, 30 minute, after second",
   118  			at: &AtTime{
   119  				WeekDay: "*",
   120  				Hour:    "*",
   121  					Minute:  "10,30",
   122  			},
   123  			baseTime:   "2019-01-01 01:33:01",
   124  			expectTime: "2019-01-01 02:10:00",
   125  		},
   126  
   127  		{
   128  			description: "evey *:0 minute",
   129  			at: &AtTime{
   130  				WeekDay: "*",
   131  				Hour:    "*",
   132  				Minute:  "0",
   133  			},
   134  			baseTime:   "2019-01-01 01:59:01",
   135  			expectTime: "2019-01-01 02:00:00",
   136  		},
   137  
   138  		{
   139  			description: "evey hour",
   140  			at: &AtTime{
   141  				WeekDay: "*",
   142  				Hour:    "*",
   143  				Minute:  "",
   144  			},
   145  			baseTime:   "2019-01-01 01:33:01",
   146  			expectTime: "2019-01-01 02:00:00",
   147  		},
   148  		{
   149  			description: "at 13 hour, before",
   150  			at: &AtTime{
   151  				WeekDay: "*",
   152  				Hour:    "13",
   153  				Minute:  "",
   154  			},
   155  			baseTime:   "2019-01-01 01:33:01",
   156  			expectTime: "2019-01-01 13:00:00",
   157  		},
   158  		{
   159  			description: "at 13 hour, after",
   160  			at: &AtTime{
   161  				WeekDay: "*",
   162  				Hour:    "13",
   163  				Minute:  "",
   164  			},
   165  			baseTime:   "2019-01-01 15:33:01",
   166  			expectTime: "2019-01-02 13:00:00",
   167  		},
   168  		{
   169  			description: "at midnight",
   170  			at: &AtTime{
   171  				WeekDay: "*",
   172  				Hour:    "0",
   173  				Minute:  "",
   174  			},
   175  			baseTime:   "2019-01-01 23:33:01",
   176  			expectTime: "2019-01-02 00:00:00",
   177  		},
   178  
   179  		{
   180  			description: "at midnight weekday 9",
   181  			at: &AtTime{
   182  				WeekDay: "*",
   183  				Hour:    "0",
   184  				Minute:  "",
   185  			},
   186  			baseTime:   "2019-01-06 23:33:01",
   187  			expectTime: "2019-01-07 00:00:00",
   188  		},
   189  
   190  		{
   191  			description: "every 0 weekday",
   192  			at: &AtTime{
   193  				WeekDay: "0",
   194  				Hour:    "",
   195  				Minute:  "",
   196  			},
   197  			baseTime:   "2019-01-04 23:33:01",
   198  			expectTime: "2019-01-06 00:00:00",
   199  		},
   200  
   201  		{
   202  			description: "every 2 weekday",
   203  			at: &AtTime{
   204  				WeekDay: "2",
   205  				Hour:    "",
   206  				Minute:  "",
   207  			},
   208  			baseTime:   "2019-01-04 23:33:01",
   209  			expectTime: "2019-01-08 00:00:00",
   210  		},
   211  
   212  		{
   213  			description: "every 2nd weekday - overlaps with base time",
   214  			at: &AtTime{
   215  				WeekDay: "2",
   216  				Hour:    "",
   217  				Minute:  "",
   218  			},
   219  			baseTime:   "2019-01-08 23:33:01",
   220  			expectTime: "2019-01-15 00:00:00",
   221  		},
   222  		{
   223  			description: "every 5 weekday in the future",
   224  			at: &AtTime{
   225  				WeekDay: "2,5",
   226  				Hour:    "",
   227  				Minute:  "",
   228  			},
   229  			baseTime:   "2019-01-09 23:33:01",
   230  			expectTime: "2019-01-11 00:00:00",
   231  		},
   232  		{
   233  			description: "every 5 weekday in the future tz",
   234  			at: &AtTime{
   235  				WeekDay: "2,5",
   236  				Hour:    "",
   237  				Minute:  "",
   238  				TZ:      "America/Los_Angeles",
   239  			},
   240  			baseTime:   "2019-01-09 23:33:01",
   241  			expectTime: "2019-01-11 00:00:00",
   242  		},
   243  	}
   244  
   245  	for _, useCase := range useCases {
   246  
   247  		err := useCase.at.Init()
   248  		assert.Nil(t, err)
   249  
   250  		var loc *time.Location
   251  		if useCase.at.TZ != "" {
   252  			loc, _ = time.LoadLocation(useCase.at.TZ)
   253  		}
   254  		var baseTime time.Time
   255  		if loc != nil {
   256  			baseTime, err = time.ParseInLocation(timeLayout, useCase.baseTime, loc)
   257  			assert.Nil(t, err, useCase.description)
   258  		} else {
   259  			baseTime, err = time.Parse(timeLayout, useCase.baseTime)
   260  			assert.Nil(t, err, useCase.description)
   261  
   262  		}
   263  
   264  		var expectTime time.Time
   265  		if loc != nil {
   266  			expectTime, err = time.ParseInLocation(timeLayout, useCase.expectTime, loc)
   267  			assert.Nil(t, err, useCase.description)
   268  		} else {
   269  			expectTime, err = time.Parse(timeLayout, useCase.expectTime)
   270  			assert.Nil(t, err, useCase.description)
   271  
   272  		}
   273  		actualTime := useCase.at.Next(baseTime)
   274  		assert.Equal(t, expectTime, actualTime, useCase.description)
   275  
   276  		//without tz
   277  		baseTime, err = time.Parse(timeLayout, useCase.baseTime)
   278  		actualTime = useCase.at.Next(baseTime)
   279  		assert.Equal(t, expectTime, actualTime, useCase.description)
   280  
   281  	}
   282  
   283  }
   284  
   285  func TestNewDuration(t *testing.T) {
   286  
   287  	var useCases = []struct {
   288  		description string
   289  		value       int
   290  		unit        string
   291  		expected    time.Duration
   292  		hasError    bool
   293  	}{
   294  		{
   295  			description: "sec test",
   296  			value:       3,
   297  			unit:        DurationSecond,
   298  			expected:    3 * time.Second,
   299  		},
   300  		{
   301  			description: "min test",
   302  			value:       4,
   303  			unit:        DurationMinute,
   304  			expected:    4 * time.Minute,
   305  		},
   306  		{
   307  			description: "hour test",
   308  			value:       5,
   309  			unit:        DurationHour,
   310  			expected:    5 * time.Hour,
   311  		},
   312  		{
   313  			description: "day test",
   314  			value:       12,
   315  			unit:        DurationDay,
   316  			expected:    12 * time.Hour * 24,
   317  		},
   318  		{
   319  			description: "week test",
   320  			value:       7,
   321  			unit:        DurationWeek,
   322  			expected:    7 * time.Hour * 24 * 7,
   323  		},
   324  		{
   325  			description: "error test",
   326  			value:       4,
   327  			unit:        "abc",
   328  			hasError:    true,
   329  		},
   330  	}
   331  
   332  	for _, useCase := range useCases {
   333  		actual, err := NewDuration(useCase.value, useCase.unit)
   334  		if useCase.hasError {
   335  			assert.NotNil(t, err, useCase.description)
   336  			continue
   337  		} else if err != nil {
   338  			assert.Nil(t, err, useCase.description)
   339  			continue
   340  		}
   341  		assert.Equal(t, useCase.expected, actual, useCase.description)
   342  
   343  	}
   344  
   345  }
   346  
   347  func TestIdMatcher_Match(t *testing.T) {
   348  	{
   349  		ts, err := TimeAt("1 sec ahead")
   350  		assert.Nil(t, err)
   351  		assert.EqualValues(t, ts.Unix()-1, time.Now().Unix())
   352  	}
   353  	{ //invalid duration unit
   354  		_, err := TimeAt("1 d ahead")
   355  		assert.NotNil(t, err)
   356  	}
   357  }
   358  
   359  func TestTimeDiff(t *testing.T) {
   360  	var useCases = []struct {
   361  		description string
   362  		base        time.Time
   363  		expression  string
   364  		exectedDiff time.Duration
   365  		hasError    bool
   366  	}{
   367  		{
   368  			description: "now test",
   369  			expression:  "now",
   370  			base:        time.Now(),
   371  			exectedDiff: 0,
   372  		},
   373  		{
   374  			description: "tomorrow test",
   375  			expression:  "tomorrow",
   376  			base:        time.Now(),
   377  			exectedDiff: time.Hour * 24,
   378  		},
   379  		{
   380  			description: "yesterday test",
   381  			expression:  "yesterday",
   382  			base:        time.Now(),
   383  			exectedDiff: -time.Hour * 24,
   384  		},
   385  		{
   386  			description: "empty expr error",
   387  			hasError:    true,
   388  		},
   389  		{
   390  			description: "parsing expr error",
   391  			expression:  "a232",
   392  			hasError:    true,
   393  		},
   394  		{
   395  			description: "2 days ago test",
   396  			expression:  "2daysago",
   397  			base:        time.Now(),
   398  			exectedDiff: -time.Hour * 48,
   399  		},
   400  
   401  		{
   402  			description: "2 days in the future",
   403  			expression:  "2day in the future",
   404  			base:        time.Now(),
   405  			exectedDiff: time.Hour * 48,
   406  		},
   407  
   408  		{
   409  			description: "days in the future",
   410  			expression:  "day InTheFuture",
   411  			base:        time.Now(),
   412  			exectedDiff: time.Hour * 24,
   413  		},
   414  
   415  		{
   416  			description: "2 hours before",
   417  			expression:  "2hourbefore",
   418  			base:        time.Now(),
   419  			exectedDiff: -time.Hour * 2,
   420  		},
   421  		{
   422  			description: "2 hours later",
   423  			expression:  "2 hoursLater",
   424  			base:        time.Now(),
   425  			exectedDiff: time.Hour * 2,
   426  		},
   427  		{
   428  			description: "timezone",
   429  			expression:  "nowInUTC",
   430  			base:        time.Now(),
   431  			exectedDiff: 0,
   432  		},
   433  
   434  		{
   435  			description: "invalid timezone error",
   436  			expression:  "nowInBAAA",
   437  			base:        time.Now(),
   438  			hasError:    true,
   439  		},
   440  
   441  		{
   442  			description: "day in UTC",
   443  			expression:  "2 days ago in UTC",
   444  			base:        time.Now(),
   445  			exectedDiff: -time.Hour * 48,
   446  		},
   447  
   448  		{
   449  			description: "day in UTC",
   450  			expression:  "weekAheadInUTC",
   451  			base:        time.Now(),
   452  			exectedDiff: time.Hour * 24 * 7,
   453  		},
   454  	}
   455  
   456  	for _, useCase := range useCases {
   457  		actual, err := TimeDiff(useCase.base, useCase.expression)
   458  		if useCase.hasError {
   459  			assert.NotNil(t, err, useCase.description)
   460  			continue
   461  		} else if err != nil {
   462  			assert.Nil(t, err, useCase.description)
   463  			continue
   464  		}
   465  		expected := useCase.base.Add(useCase.exectedDiff)
   466  		assert.EqualValues(t, expected.Unix(), actual.Unix(), useCase.description)
   467  
   468  	}
   469  
   470  }
   471  
   472  func TestDayElapsedInPct(t *testing.T) {
   473  
   474  	t0, _ := time.Parse(DateFormatToLayout("yyyy-MM-dd hh:mm:ss"), "2017-01-01 12:00:00")
   475  	elapsedPct := ElapsedDay(t0)
   476  	assert.EqualValues(t, 50, math.Round(100*elapsedPct))
   477  
   478  	elapsed, err := ElapsedToday("")
   479  	assert.Nil(t, err)
   480  	assert.True(t, elapsed > 0)
   481  
   482  	remaining, err := RemainingToday("")
   483  	assert.Nil(t, err)
   484  	assert.True(t, remaining > 0)
   485  	assert.EqualValues(t, int(remaining+elapsed), 1)
   486  
   487  }
   488  
   489  func TestTimeWindow_Range(t *testing.T) {
   490  
   491  	var useCaes = []struct {
   492  		description   string
   493  		window        *TimeWindow
   494  		expectedCount int
   495  	}{
   496  		{
   497  			description:   "empty window",
   498  			window:        &TimeWindow{},
   499  			expectedCount: 1,
   500  		},
   501  		{
   502  			description: "loopback window",
   503  			window: &TimeWindow{
   504  				TimeFormat: "yyyy-MM-dd HH:mm:ss",
   505  				Loopback:   &Duration{Value: 3, Unit: "sec"},
   506  				EndDate:    "2011-12-01 15:01:01",
   507  				Interval:   &Duration{Value: 1, Unit: "sec"},
   508  			},
   509  			expectedCount: 4,
   510  		},
   511  		{
   512  			description: "default loopback with interval window",
   513  			window: &TimeWindow{
   514  				Loopback: &Duration{Value: 3, Unit: "min"},
   515  				Interval: &Duration{Value: 1, Unit: "min"},
   516  			},
   517  			expectedCount: 4,
   518  		},
   519  		{
   520  			description: "default loopback window",
   521  			window: &TimeWindow{
   522  				Loopback: &Duration{Value: 3, Unit: "min"},
   523  			},
   524  			expectedCount: 2,
   525  		},
   526  		{
   527  			description: "date range window",
   528  			window: &TimeWindow{
   529  				TimeFormat: "yyyy-MM-dd HH:mm:ss",
   530  				StartDate:  "2011-12-01 15:01:01",
   531  				EndDate:    "2011-12-01 15:02:01",
   532  				Interval:   &Duration{Value: 10, Unit: "sec"}},
   533  			expectedCount: 7,
   534  		},
   535  	}
   536  
   537  	for _, useCase := range useCaes {
   538  		count := 0
   539  		err := useCase.window.Range(func(time time.Time) (bool, error) {
   540  			count++
   541  			return true, nil
   542  		})
   543  		assert.Nil(t, err, useCase.description)
   544  		assert.Equal(t, useCase.expectedCount, count, useCase.description)
   545  	}
   546  
   547  }
   548  
   549  
   550  func TestN(t *testing.T) {
   551  
   552  
   553  }