2016-04-14 9 views
7

Ho un time.Time creato utilizzando time.Date(). Quindi calcolo il numero di nanosecondi tra 1970/1/1 00:00:00.000000000 e quella volta.Perché le 2 strutture temporali con la stessa data e ora restituiscono false se confrontate con ==?

Quindi prendo i nanosecondi e li trasformo in time.Time utilizzando time.Unix().

Tuttavia, se si confronta il tempo ricostituito con l'originale utilizzando ==, restituisce false. Se sottraggo queste 2 volte, la durata risultante è 0. Se confronto queste 2 volte usando time.Equal(), restituisce true.

Se creo un'altra volta utilizzando time.Date() con gli stessi valori della prima volta, utilizzando == per confrontare questo nuovo orario e il tempo originale risulta in un valore vero.

Questo è il codice che dimostra questa (Golang Playground):

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    t1 := time.Date(2016, 4, 14, 1, 30, 30, 222000000, time.UTC) 


    base := time.Date(1970, 1, 1, 0, 0, 0, 0, t1.Location()) 
    nsFrom1970 :=t1.Sub(base).Nanoseconds() // Calculate the number of nanoseconds from 1970/1/1 to t1 

    t2 := time.Unix(0, nsFrom1970) 

    fmt.Println(t1) 
    fmt.Println(t2) 
    fmt.Println(t1.Sub(t2)) // 0 
    fmt.Println(t1 == t2) //false 
    fmt.Println(t1.Equal(t2)) //true 

    t3 := time.Date(2100, 2, 1, 21, 21, 21, 222000000, time.UTC) 
    fmt.Println(t1 == t3) //true 
} 

Perché il tempo ricostituito restituire false se confrontato con il tempo originale?

risposta

5

time.Time è un struct. Quando si tenta di confrontarli con ==, citando il Spec: Comparison operator:

valori Struct sono paragonabili, se tutti i loro campi sono comparabili. Due valori di struttura sono uguali se i corrispondenti campi non blank sono uguali.

Quindi t1 == t2 confronterà tutti i campi dei valori della struttura 2 Time. La struttura Time contiene non solo il secondo e il nanosecondo dall'ora di base, ma contiene anche la posizione come puntatore: *Location, quindi == confronterà anche i campi di posizione. Comparazione dei puntatori:

I valori dei puntatori sono confrontabili. Due valori di puntatore sono uguali se puntano alla stessa variabile o se entrambi hanno il valore nil. I puntatori alle variabili distinte zero-size possono o non possono essere uguali.

e questo è il motivo per cui si confrontano i tempi con == dà un risultato false: 2 posizioni possono denotano la stessa posizione anche se il loro indirizzo è diverso, e questo è il vostro caso.

per dimostrare questo:

fmt.Println("Locations:", t1.Location(), t2.Location()) 
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location()) 
fmt.Println("Locations equal:", t1.Location() == t2.Location()) 

uscita:

Locations: UTC UTC 
Location pointers: 0x1e2100 0x1e6de0 
Locations equal: false 

Questo è documentato in time.Time:

Si noti che il Go == operatore non confronta solo l'istante di tempo, ma anche la posizione. Pertanto, i valori di tempo non devono essere utilizzati come chiavi di mappa o database senza prima garantire che la stessa posizione sia stata impostata per tutti i valori, che può essere ottenuta utilizzando l'UTC o il metodo locale.

Se t1 e t2 sarebbe anche contenere lo stesso puntatore *Location, sarebbero uguali, anche se confrontato con l'operatore ==. Questo può essere assicurato chiamando Time.UTC() o Time.Local() metodo sopra che restituisce un valore time.Time cui viene utilizzato lo stesso puntatore posizione (*Location). Oppure utilizzando il metodo Time.In() che impostare il puntatore posizione specificata (dopo la conversione corretta), ad es .:

t2 = t2.In(t1.Location()) 
fmt.Println("Locations:", t1.Location(), t2.Location()) 
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location()) 
fmt.Println("Locations equal:", t1.Location() == t2.Location()) 
fmt.Println(t1 == t2)  // Now true 
fmt.Println(t1.Equal(t2)) // Still true 

uscita:

Locations: UTC UTC 
Location pointers: 0x1e2100 0x1e2100 
Locations equal: true 
true 
true 

Prova sul Go Playground.

Problemi correlati