Czy są jakieś opcje porównywania dat w Go? Muszę sortować dane po dacie i godzinie - niezależnie. Mogę więc dopuścić obiekt, który pojawia się w określonym zakresie dat, o ile występuje również w określonym przedziale czasu. W tym modelu nie mogłem po prostu wybrać najstarszej daty, najmłodszego czasu / najnowszej daty, najnowszego czasu i sekund Unix (), aby je porównać. Byłbym wdzięczny za wszelkie sugestie.
Ostatecznie napisałem moduł porównywania ciągów parsujących czas, aby sprawdzić, czy czas mieści się w zakresie. Jednak nie jest to zbyt dobre; Mam kilka nierozpoznanych problemów. Opublikuję to tutaj dla zabawy, ale mam nadzieję, że istnieje lepszy sposób na porównanie czasu.
package main
import (
"strconv"
"strings"
)
func tryIndex(arr []string, index int, def string) string {
if index <= len(arr)-1 {
return arr[index]
}
return def
}
/*
* Takes two strings of format "hh:mm:ss" and compares them.
* Takes a function to compare individual sections (split by ":").
* Note: strings can actually be formatted like "h", "hh", "hh:m",
* "hh:mm", etc. Any missing parts will be added lazily.
*/
func timeCompare(a, b string, compare func(int, int) (bool, bool)) bool {
aArr := strings.Split(a, ":")
bArr := strings.Split(b, ":")
// Catches margins.
if (b == a) {
return true
}
for i := range aArr {
aI, _ := strconv.Atoi(tryIndex(aArr, i, "00"))
bI, _ := strconv.Atoi(tryIndex(bArr, i, "00"))
res, flag := compare(aI, bI)
if res {
return true
} else if flag { // Needed to catch case where a > b and a is the lower limit
return false
}
}
return false
}
func timeGreaterEqual(a, b int) (bool, bool) {return a > b, a < b}
func timeLesserEqual(a, b int) (bool, bool) {return a < b, a > b}
/*
* Returns true for two strings formmated "hh:mm:ss".
* Note: strings can actually be formatted like "h", "hh", "hh:m",
* "hh:mm", etc. Any missing parts will be added lazily.
*/
func withinTime(timeRange, time string) bool {
rArr := strings.Split(timeRange, "-")
if timeCompare(rArr[0], rArr[1], timeLesserEqual) {
afterStart := timeCompare(rArr[0], time, timeLesserEqual)
beforeEnd := timeCompare(rArr[1], time, timeGreaterEqual)
return afterStart && beforeEnd
}
// Catch things like `timeRange := "22:00:00-04:59:59"` which will happen
// with UTC conversions from local time.
// THIS IS THE BROKEN PART I BELIEVE
afterStart := timeCompare(rArr[0], time, timeLesserEqual)
beforeEnd := timeCompare(rArr[1], time, timeGreaterEqual)
return afterStart || beforeEnd
}
Więc TLDR, napisałem funkcję withinTimeRange (zakres, czas), ale nie działa ona całkowicie poprawnie. (W rzeczywistości przeważnie tylko drugi przypadek, w którym zakres czasu przecina się przez dni, jest zepsuty. Oryginalna część działała, właśnie zdałem sobie sprawę, że muszę to uwzględnić podczas konwersji na UTC z lokalnego.)
Jeśli istnieje lepszy (najlepiej wbudowany) sposób, chciałbym o tym usłyszeć!
UWAGA: Jako przykład rozwiązałem ten problem w Javascript za pomocą tej funkcji:
function withinTime(start, end, time) {
var s = Date.parse("01/01/2011 "+start);
var e = Date.parse("01/0"+(end=="24:00:00"?"2":"1")+"/2011 "+(end=="24:00:00"?"00:00:00":end));
var t = Date.parse("01/01/2011 "+time);
return s <= t && e >= t;
}
Jednak naprawdę chcę zrobić ten filtr po stronie serwera.
źródło
Do porównania między dwoma czasami użyj czasu.
// utc life loc, _ := time.LoadLocation("UTC") // setup a start and end time createdAt := time.Now().In(loc).Add(1 * time.Hour) expiresAt := time.Now().In(loc).Add(4 * time.Hour) // get the diff diff := expiresAt.Sub(createdAt) fmt.Printf("Lifespan is %+v", diff)
Program wyprowadza:
Lifespan is 3h0m0s
http://play.golang.org/p/bbxeTtd4L6
źródło
W przypadku, gdy koniec interwału to data bez godzin, np. „Od 01.01.2017 do 16.01.2017”, lepiej ustawić interwał na 23 godziny 59 minut i 59 sekund, na przykład:
end = end.Add(time.Duration(23*time.Hour) + time.Duration(59*time.Minute) + time.Duration(59*time.Second)) if now.After(start) && now.Before(end) { ... }
źródło
Najnowsze protokoły preferują użycie RFC3339 na dokumentację pakietu czasu golang .
cutOffTime, _ := time.Parse(time.RFC3339, "2017-08-30T13:35:00Z") // POSTDATE is a date time field in DB (datastore) query := datastore.NewQuery("db").Filter("POSTDATE >=", cutOffTime).
źródło
Poniższe rozwiązało mój problem z konwersją ciągu znaków na datę
pakiet główny
import ( "fmt" "time" ) func main() { value := "Thu, 05/19/11, 10:47PM" // Writing down the way the standard time would look like formatted our way layout := "Mon, 01/02/06, 03:04PM" t, _ := time.Parse(layout, value) fmt.Println(t) } // => "Thu May 19 22:47:00 +0000 2011"
Dzięki Paulowi Adamowi Smithowi
źródło