Created
October 2, 2019 10:19
-
-
Save invidian/346b0ea57f20677ce5ae74b410e5cbe1 to your computer and use it in GitHub Desktop.
Golang calculating max time
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"time" | |
) | |
// hoursSince returns how many hours passed from given date. | |
// for Time 0 (time.Time{}), it returns 0. | |
func hoursSince(d time.Time) int { | |
// Get current year | |
y, _, _ := d.Date() | |
// Golang time starts from 1 | |
y = y - 1 | |
// Hours in non-leap years | |
normalHours := y * 365 * 24 | |
// Hours in leap years | |
leapHours := (y / 4) * 24 | |
// Calculate remaining hours since beginning of the year and remove hours in Time 0. | |
remainingHours := int(d.Sub(time.Date(y, 0, 0, 0, 0, 0, 0, time.UTC)).Round(time.Hour).Hours()) - int(time.Time{}.Sub(time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC)).Round(time.Hour).Hours()) | |
return normalHours + leapHours + remainingHours | |
} | |
func main() { | |
// Snapshot current time | |
t := time.Now() | |
// Max golang date before it overflows | |
// Calculate max date golang can handle. AddDate is easier to use than time.Date() since we don't have to calculate number of months | |
tMax := time.Time{}.AddDate(292277026853, 0, 312).Add((time.Duration(7) * time.Hour) + (time.Duration(15) * time.Second) + (time.Duration(999) * time.Millisecond) + (time.Duration(999) * time.Microsecond) + (time.Duration(999) * time.Nanosecond)) | |
// h represents max number of hours we can add to a current time before it overflows | |
h := hoursSince(tMax) - hoursSince(t) - 3 // +1 | |
// If hours now + added hours are bigged than max time, panic | |
if hoursSince(t)+h > hoursSince(tMax)-3 { | |
panic(fmt.Sprintf("Added time overflows the universe, max value possible to add is %d", hoursSince(tMax)-2)) | |
} | |
fmt.Printf("Now is %s\n", t) | |
fmt.Println() | |
fmt.Printf("Attempting to add %d hours\n", h) | |
fmt.Println() | |
// First, calculate how many days we have to add | |
days := h / 24 | |
fmt.Printf("%d days to add\n", days) | |
// Calculate how many years we have in calculated days, this considers leap years as well | |
years := (days / ((365 * 4) + 1)) * 4 | |
// Since we have years now, get remaining days we have left | |
days = days % ((365 * 4) + 1) | |
fmt.Printf("Adding %d years, %d days\n", years, days) | |
// Add calculated years and days to current date | |
t = t.AddDate(years, 0, days) | |
fmt.Printf("Now is %s\n", t) | |
fmt.Println() | |
// There are some hours left to add after /24 division, get them with module and add as well | |
h = h % 24 | |
fmt.Printf("%d hours remaining to add\n", h) | |
fmt.Println() | |
fmt.Printf("Adding %d hours\n", h) | |
// We can't simply put entire h into time.Duration() as time.Duration overflows only after 290 years | |
t = t.Add(time.Duration(h) * time.Hour) | |
fmt.Printf("Now is %s\n", t) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment