diff --git a/cryptor/rsa_private_example.pem b/cryptor/rsa_private_example.pem index 0949b05..88d252d 100644 --- a/cryptor/rsa_private_example.pem +++ b/cryptor/rsa_private_example.pem @@ -1,51 +1,51 @@ -----BEGIN rsa private key----- -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 -----END rsa private key----- diff --git a/cryptor/rsa_public_example.pem b/cryptor/rsa_public_example.pem index 2ee7341..724d49d 100644 --- a/cryptor/rsa_public_example.pem +++ b/cryptor/rsa_public_example.pem @@ -1,14 +1,14 @@ -----BEGIN rsa public key----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsELqn9abxs7ZK81Ipbp5 -+E/5SrOQycAalnRCES3YPOoAV3Ir+99WjEi9Ak4EYS3VrvgISSNiRx1tHDNpBlBq -GF+Mww8wAUmrcXsEndbHma/g3zHGueua9GK0l+hQJ/grkatykgD81gam/SPOMPnJ -SsoQlsTgM47ZHM35adiXqL/gDMZ70lQdB2+03WJXlvfYZWpHsXDqUkveEZbLgZST -36ax8ap+Ge2GoLlD1sNapRxMBH1PGNdzSdV7ZJmzQ3WmjwDAddLX73YE6vhR5tDA -XhrSweNPtIjUhGJsgkW9VTEQWeW9cZmFo/jYuvEDgBnZOh1DJe2BHx06Ymr8Zcgs -OBYddANsk750II8+qUnBekiJkpo0ldCK2VnsLoLM3YCf3Lk7VYuHP6KiCXyh6Fzb -Y1DTRHJRpMJYT8t5xyQis581DbRVPkcse3ig5KsQLe5XXbBBegVrQJpy1b440uZV -W2eSpStX5ZAfNVsU0ZPdI4/i6UNMEa6c7tf83S21Q0K6SEZ5PrfBJECRDxFzJWea -mwppHY8fdeItVk/cxBJ9XRyOyG9pJKMnOMFD++LzGP6uL5FKov7BSplOIMqsJzwh -4zkIjAhgbGVQZm17kg1xvF30c2fgijNEoSIuVWJzlQyQ9cmSaSmmi+SPmf/C/IcU -DF0nikERs1v58vNESvcZP80CAwEAAQ== +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAm1rBCE+U+7M46S21q0yo +ygTXHlhnZZ6IfQwRCK24EFQ6yBxtemHKjNuHEIQ/DlSh+B5DRX/bCHQ/m5c0yrNP +iMKv9N3K4e8Wv/pBVqAsSmF2nSjxpXSraIACqrNSAig8MzUJ8pZq5d/9Le1AXNRa +0aqHbw9YoLQJKACrdY4YbDi1NXU2ADImpnaSON0VJt5sdqA8OrEVOhm02DA4KEsh +JXAp2pR4h3KT82Fuj0dMKB1iKAInXo8OeYwKgcjBxNZK4mPo6JT0ejYnFwhgtPaL +lUm0BpXAqI2eclvhn+LmM9Q/S1mvDCeLdNgQ8rh1+qPBXkCesskyu2hyuY3/H+Wj +Q4PHjF++lCnuRv/GJYIgbUnLxKP4cxsB+jj7SU+ltgADZoLyNeUpQ9QxY8FNbKDx +JKnA7khtmvHjE4PKdy2e4M4mVcMheOtJdjvxhA2SEh9xnzP5G2JSHzE3877evInp +QCJb+bfEG533B5Yrgm85C+sPcxrK684+Dmn+Y3wdQQNJgYgQGZDGDIRY8stWpRX9 +G2dnWQfVtZLmSM5WwVPeI4wa6dxizk/ukylsgk9E5zJjZlPx8Fx2hnTsrNSARl0g +CdbhGhRjHlVFjKI80z+evPXLCYn8B4CwWsg6ExBZSOAvcrN7XZFcalDCT5CqsNpb +Cg/7SXO87v8KL/54fKUc4qsCAwEAAQ== -----END rsa public key----- diff --git a/datetime/datetime.go b/datetime/datetime.go index dd6f4e1..67e1474 100644 --- a/datetime/datetime.go +++ b/datetime/datetime.go @@ -443,3 +443,50 @@ func GenerateDatetimesBetween(start, end time.Time, layout string, interval stri return result, nil } + +// Min returns the earliest time among the given times. +// Play: todo +func Min(t1 time.Time, times ...time.Time) time.Time { + minTime := t1 + + for _, t := range times { + if t.Before(minTime) { + minTime = t + } + } + + return minTime +} + +// Max returns the latest time among the given times. +// Play: todo +func Max(t1 time.Time, times ...time.Time) time.Time { + maxTime := t1 + + for _, t := range times { + if t.After(maxTime) { + maxTime = t + } + } + + return maxTime +} + +// MaxMin returns the latest and earliest time among the given times. +// Play: todo +func MaxMin(t1 time.Time, times ...time.Time) (maxTime time.Time, minTime time.Time) { + maxTime = t1 + minTime = t1 + + for _, t := range times { + if t.Before(minTime) { + minTime = t + } + + if t.After(maxTime) { + maxTime = t + } + } + + return maxTime, minTime +} diff --git a/datetime/datetime_example_test.go b/datetime/datetime_example_test.go index 99098bc..da0b1c5 100644 --- a/datetime/datetime_example_test.go +++ b/datetime/datetime_example_test.go @@ -437,3 +437,32 @@ func ExampleGenerateDatetimesBetween() { // [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00] // } + +func ExampleMin() { + result := Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC)) + + fmt.Println(result) + + // Output: + // 2024-09-01 00:00:00 +0000 UTC +} + +func ExampleMax() { + result := Max(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC)) + + fmt.Println(result) + + // Output: + // 2024-09-02 00:00:00 +0000 UTC +} + +func ExampleMaxMin() { + max, min := MaxMin(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 3, 0, 0, 0, 0, time.UTC)) + + fmt.Println(max) + fmt.Println(min) + + // Output: + // 2024-09-03 00:00:00 +0000 UTC + // 2024-09-01 00:00:00 +0000 UTC +} diff --git a/datetime/datetime_test.go b/datetime/datetime_test.go index ee90ff9..acb7020 100644 --- a/datetime/datetime_test.go +++ b/datetime/datetime_test.go @@ -521,3 +521,60 @@ func TestGenerateDatetimesBetween(t *testing.T) { } }) } + +func TestMin(t *testing.T) { + t.Parallel() + + assert := internal.NewAssert(t, "TestMin") + + zeroTime := time.Time{} + now := time.Now() + oneMinuteAgo := now.Add(-time.Minute) + oneMinuteAfter := now.Add(time.Minute) + + assert.Equal(zeroTime, Min(zeroTime, now, oneMinuteAgo, oneMinuteAfter)) + + assert.Equal(zeroTime, Min(now, zeroTime)) + + assert.Equal(oneMinuteAgo, Min(oneMinuteAgo, now, oneMinuteAfter)) +} + +func TestMax(t *testing.T) { + t.Parallel() + + assert := internal.NewAssert(t, "TestMax") + + zeroTime := time.Time{} + now := time.Now() + oneMinuteAgo := now.Add(-time.Minute) + oneMinuteAfter := now.Add(time.Minute) + + assert.Equal(oneMinuteAfter, Max(zeroTime, now, oneMinuteAgo, oneMinuteAfter)) + + assert.Equal(now, Max(now, zeroTime)) + + assert.Equal(oneMinuteAfter, Max(oneMinuteAgo, now, oneMinuteAfter)) +} + +func TestMaxMin(t *testing.T) { + t.Parallel() + + assert := internal.NewAssert(t, "TestMinMax") + + zeroTime := time.Time{} + now := time.Now() + oneMinuteAgo := now.Add(-time.Minute) + oneMinuteAfter := now.Add(time.Minute) + + max, min := MaxMin(zeroTime, now, oneMinuteAgo, oneMinuteAfter) + assert.Equal(zeroTime, min) + assert.Equal(oneMinuteAfter, max) + + max, min = MaxMin(now, zeroTime) + assert.Equal(zeroTime, min) + assert.Equal(now, max) + + max, min = MaxMin(oneMinuteAgo, now, oneMinuteAfter) + assert.Equal(oneMinuteAgo, min) + assert.Equal(oneMinuteAfter, max) +}