วิธีเปรียบเทียบวันที่ / เวลา


102

มีตัวเลือกในการเปรียบเทียบวันที่ใน Go หรือไม่? ฉันต้องจัดเรียงข้อมูลตามวันที่และเวลาโดยอิสระ ดังนั้นฉันอาจอนุญาตให้ออบเจ็กต์ที่เกิดขึ้นภายในช่วงวันที่ตราบเท่าที่มันเกิดขึ้นในช่วงเวลาด้วย ในโมเดลนี้ฉันไม่เพียงแค่เลือกวันที่ที่เก่าที่สุดเวลาที่อายุน้อยที่สุด / วันที่ล่าสุดเวลาล่าสุดและ Unix () วินาทีมาเปรียบเทียบกัน ฉันขอขอบคุณสำหรับคำแนะนำใด ๆ

ในท้ายที่สุดฉันเขียนโมดูลเปรียบเทียบสตริงแยกวิเคราะห์เวลาเพื่อตรวจสอบว่าเวลาอยู่ในช่วงหรือไม่ อย่างไรก็ตามนี่ไม่ใช่เรื่องที่ดีนัก ฉันมีปัญหาที่อ้าปากค้าง ฉันจะโพสต์ที่นี่เพื่อความสนุกสนาน แต่ฉันหวังว่าจะมีวิธีเปรียบเทียบเวลาที่ดีกว่านี้

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

อย่างไรก็ตามฉันต้องการทำตัวกรองฝั่งเซิร์ฟเวอร์

คำตอบ:


117

ใช้แพ็กเกจเวลาเพื่อทำงานกับข้อมูลเวลาใน Go

เวลาสามารถเปรียบเทียบได้โดยใช้วิธี Before, After และ Equal เมธอดย่อยจะลบสองอินสแตนซ์โดยสร้าง Duration วิธีการเพิ่มจะเพิ่มเวลาและระยะเวลาโดยสร้างเวลา

ตัวอย่างการเล่น :

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, ".")
    }
}

1
บางทีฉันอ่านไม่ออก แต่ฉันไม่เห็นอะไรเกี่ยวกับการเปรียบเทียบเวลาเลย ถ้ามีคุณช่วยชี้ให้ฉันดูบทความที่แน่นอนได้ไหม
eatonphil

12
ลองใช้godoc.org/time#Time.Equalหรือgodoc.org/time#Time Afterสำหรับการเปรียบเทียบอย่างง่ายหรือgodoc.org/time#Time ติดตามเพื่อค้นหาความแตกต่างระหว่างสองครั้ง
andybalholm

1
"รายงานว่าเวลา t ทันทีหลังคุณ" น่าขนลุก
ดาเมียน Roche

25

เพื่อเปรียบเทียบระหว่างเวลาใช้งานสองครั้ง 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


1
นี่คือคำตอบที่ดีที่สุด
MithunS

15

สำหรับในกรณีที่ช่วงเวลาของคุณสิ้นสุดลงเป็นวันที่โดยไม่มีชั่วโมงเช่น "ตั้งแต่วันที่ 01-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) {
    ...
}

1
สิ่งที่ฉันต้องการในการเปรียบเทียบ TimeStamp ที่เก็บไว้กับเวลาปัจจุบัน
PGP_Protector

1

โปรโตคอลล่าสุดต้องการการใช้งานของ RFC3339 ต่อเอกสารแพคเกจเวลา golang

โดยทั่วไปควรใช้ RFC1123Z แทน RFC1123 สำหรับเซิร์ฟเวอร์ที่ยืนยันในรูปแบบนั้นและควรใช้ RFC3339 สำหรับโปรโตคอลใหม่ RFC822, RFC822Z, RFC1123 และ RFC1123Z มีประโยชน์สำหรับการจัดรูปแบบ เมื่อใช้กับเวลาแยกวิเคราะห์พวกเขาไม่ยอมรับรูปแบบเวลาทั้งหมดที่อนุญาตโดย RFCs

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

-2

ต่อไปนี้แก้ปัญหาของฉันในการแปลงสตริงเป็นวันที่

แพคเกจหลัก

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"

ขอบคุณ paul adam smith


1
นั่นเป็นสิ่งที่ดี แต่ไม่มีส่วนเกี่ยวข้องกับคำถามมากนักใช่ไหม
matthias krull

คุณมีสิทธิ์ @matthiaskrull ไม่ตอบคำถามเรื่องการเปรียบเทียบวันที่ แต่บางส่วนช่วยในการแยกวิเคราะห์วันที่ได้อย่างง่ายดาย
suryakrupa

ทำเช่นนี้และอีกสองสามอย่าง ฉันแค่บอกว่าการเชื่อมโยงบางสิ่งในความคิดเห็นน่าจะเหมาะกว่าที่จะตอบด้วยบิตที่มีประโยชน์แบบสุ่ม
matthias krull
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.