2014-01-04 7 views
39

Есть ли какие-либо варианты сравнения даты в Голанге? Я должен сортировать данные на основе даты и времени - независимо. Поэтому я могу разрешить объект, который встречается в пределах диапазона дат, если он также встречается в течение нескольких раз. В этой модели я просто не мог просто выбрать самую старую дату, самую младшую дату/последнюю дату, последнее время и Unix() секунды. Я бы очень признателен за любые предложения.Сравнение даты/времени в golang

В конечном счете, я написал модуль сравнения строк времени, чтобы проверить, находится ли время в пределах диапазона. Однако это не так хорошо; У меня есть некоторые проблемы. Я отправлю это здесь просто для удовольствия, но я надеюсь, что есть лучший способ сравнить время.

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 
} 

Так что TLDR, я написал функцию WithinTimeRange (диапазон, время), но она не работает полностью правильно. (Фактически, в основном только второй случай, когда временной интервал проходит через дни, сломан. Исходная часть работала, я только понял, что мне нужно будет учитывать это при конвертации в UTC из местных.)

Если есть лучший (желательно встроенный) способ, я бы хотел услышать об этом!

ПРИМЕЧАНИЕ: Просто в качестве примера, я решил эту проблему в Javascript с помощью этой функции:

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; 
} 

Однако я действительно хочу сделать этот фильтр на стороне сервера.

+0

Я не могу поверить, что вы прошли через столько проблем, а не когда-то думали, что это чувствует, как это должно быть в sdtlib. – Kugel

ответ

41

Используйте пакет time, чтобы работать со временем в Go.

Play пример:

package main 

import (
    "fmt" 
    "time" 
) 

func inTimeSpan(start, end, check time.Time) bool { 
    return check.After(start) && check.Before(end) 
} 

func main() { 
    start, _ := time.Parse(time.RFC822, "01 Jan 15 10:00 UTC") 
    end, _ := time.Parse(time.RFC822, "01 Jan 16 10:00 UTC") 

    in, _ := time.Parse(time.RFC822, "01 Jan 15 20:00 UTC") 
    out, _ := time.Parse(time.RFC822, "01 Jan 17 10:00 UTC") 

    if inTimeSpan(start, end, in) { 
     fmt.Println(in, "is between", start, "and", end, ".") 
    } 

    if !inTimeSpan(start, end, out) { 
     fmt.Println(out, "is not between", start, "and", end, ".") 
    } 
} 
+0

Возможно, я не умею читать, но я ничего там не видел о сравнении времени. Если он есть, не могли бы вы указать мне точную статью? – eatonphil

+9

Попробуйте http://godoc.org/time#Time.Equal или http://godoc.org/time#Time.After для простого сравнения или http://godoc.org/time#Time.Sub, чтобы узнать разница между двумя временами. – andybalholm

+0

Да, это работает. Я совершенно неправильно понял это. Благодаря! – eatonphil

0

Следующая решить мою проблему преобразования строки в дату

пакет главный

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" 

Thanks to paul adam smith

+1

Это все хорошо, но не имеет большого отношения к вопросу, deos это? –

+0

Вы правы @matthaskask. Он не отвечает на вопрос о сравнении дат, но частично помогает в синтаксическом оформлении дат с легкостью. – suryakrupa

+0

Так что сделайте [это] (https://stackoverflow.com/questions/6589636/date-parsing-in-go) и еще пару других. Я просто говорю, что ссылка на что-то в комментариях будет лучше соответствовать тому, что отвечает со случайными полезными битами. –

11

Для сравнения между два раза использования time.Sub()

// 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) 

Программа выводит:

Lifespan is 3h0m0s 

http://play.golang.org/p/bbxeTtd4L6

4

Для случая, когда конец вашего интервала в это дата без часов, как «от 2017-01- 01 на весь день 2017-01-16 «лучше отрегулировать интервал до 23 часов 59 минут и 59 секунд, как:

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) { 
    ... 
} 
0

Последние протоколы предпочитают использование RFC3339 за golang time package documentation.

В целом RFC1123Z следует использовать вместо RFC1123 для серверов, которые настаивают на этом формате, и RFC3339 должен быть предпочтительнее для новых протоколов. RFC822, RFC822Z, RFC1123 и RFC1123Z полезны для форматирования; когда они используются со временем. Они не принимают все форматы времени, разрешенные RFC.

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). 
Смежные вопросы