2016-04-14 10 views
7

time.Date()を使用してtime.Timeを作成しました。私は1970/1/1 00:00:00.000000000とその時間の間のナノ秒数を計算します。==と比較すると、同じ日付と時刻の2回の構造体がfalseを返すのはなぜですか?

次に、ナノ秒をとり、を使用してtime.Timeに戻します。

ただし、再構成された時刻と元の値を==と比較すると、falseが返されます。これらの2回を引くと、結果の継続時間は0になります。time.Equal()を使ってこれらの2回を比較すると、trueを返します。

time.Date()と同じ値を最初に使用して別の時間を作成する場合は、==を使用してこの新しい時刻と元の時刻を比較すると、真となります。

これは、実証コードがあり、この(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 
} 

なぜ再構成時間はfalseを返すのですか?

答えて

5

time.Timeは、structです。あなたはSpec: Comparison operatorから引用、==でそれらを比較しようとすると:すべてのフィールドが同等である場合

構造体の値が同等です。対応する非blankフィールドが等しい場合、2つの構造体の値は等しくなります。

したがってt1 == t2は、2 Time構造体値のすべてのフィールドを比較します。 Time構造体には、基本時間から2番目と1ナノ秒だけでなく、ポインタとしての位置も含まれています:*Locationなので、==も場所フィールドを比較します。ポインタの比較:

ポインタの値は同等です。 2つのポインタ値は、同じ変数を指す場合、または両方が値nilを持つ場合、等しいです。別のzero-size変数へのポインタは等しいかもしれません。 2箇所が自分のアドレスが異なっても同じ場所を示すことができる、これはあなたのケースである:==で時間を比較すると、false結果が得られる理由

はこれがあります。

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

出力:

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

これはtime.Timeで文書化されています。このことを証明する

ゴー==演算子は、単に時刻ではなく比較することを

注けど場所も。したがって、UTCまたはローカルメソッドを使用して達成できるすべての値に対して同じロケーションが設定されていることを最初に保証しなければ、時間値をマップまたはデータベースキーとして使用しないでください。

t1

t2も同じ*Locationポインタを含むであろう場合、それらは==オペレータと比べても等しくなります。これは、同じ位置ポインタ(*Location)が使用されるtime.Timeの値を返す、Time.UTC()またはTime.Local()メソッドを呼び出すことによって保証されます。または(適切な変換後)指定された場所のポインタをセットするTime.In()方法を用いて、例えば:

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 

出力:

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

Go Playgroundにそれを試してみてください。

関連する問題