-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ea30b80
commit 1be41c1
Showing
6 changed files
with
141 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package null | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
) | ||
|
||
// Time is a nullable time.Time, that supports parsing to/from JSON. | ||
type Time struct { | ||
time.Time | ||
Valid bool | ||
} | ||
|
||
// NewTime returns a new nullable time.Time object. | ||
// This is equivalent to `null.Time{Time: t, Valid: valid}`. | ||
func NewTime(t time.Time, valid bool) Time { | ||
return Time{Time: t, Valid: valid} | ||
} | ||
|
||
// MarshalJSON implements the encoding json interface. | ||
func (t Time) MarshalJSON() ([]byte, error) { | ||
if t.Valid { | ||
return json.Marshal(t.Time) | ||
} | ||
|
||
return json.Marshal(nil) | ||
} | ||
|
||
// UnmarshalJSON implements the encoding json interface. | ||
func (t *Time) UnmarshalJSON(data []byte) error { | ||
var value time.Time | ||
|
||
if err := json.Unmarshal(data, &value); err != nil { | ||
return err | ||
} | ||
|
||
if !value.IsZero() { | ||
t.SetValid(value) | ||
} else { | ||
t.SetNil() | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// SetValid sets the value and valid to true. | ||
func (t *Time) SetValid(value time.Time) { | ||
t.Time = value | ||
t.Valid = true | ||
} | ||
|
||
// SetNil sets the value to default and valid to false. | ||
func (t *Time) SetNil() { | ||
t.Time = time.Time{} | ||
t.Valid = false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package null | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
) | ||
|
||
type testTime struct { | ||
Value Time `json:"value"` | ||
} | ||
|
||
func TestNewTime(t *testing.T) { | ||
value := NewTime(time.Now(), true) | ||
|
||
if value.Time.Equal(time.Time{}) || !value.Valid { | ||
t.Fatal("New Time must have value and be valid") | ||
} | ||
} | ||
|
||
func TestMarshalTime(t *testing.T) { | ||
now := time.Now() | ||
nowStrBytes, _ := json.Marshal(now) | ||
nowStr := string(nowStrBytes) | ||
value := Time{Time: now, Valid: true} | ||
|
||
if data, err := json.Marshal(value); err != nil || string(data) != nowStr { | ||
t.Fatalf("Time must be marshalled to value, but was %v %v", err, string(data)) | ||
} | ||
|
||
value.Valid = false | ||
|
||
if data, err := json.Marshal(value); err != nil || string(data) != "null" { | ||
t.Fatalf("Time must be marshalled to null, but was %v %v", err, string(data)) | ||
} | ||
} | ||
|
||
func TestUnmarshalTime(t *testing.T) { | ||
now := time.Now() | ||
nowStrBytes, _ := json.Marshal(now) | ||
nowStr := string(nowStrBytes) | ||
str := `{"value": `+nowStr+`}` | ||
var value testTime | ||
|
||
if err := json.Unmarshal([]byte(str), &value); err != nil { | ||
t.Fatalf("Time must be unmarshalled to value, but was %v", err) | ||
} | ||
|
||
if !value.Value.Valid || !value.Value.Time.Equal(now) { | ||
t.Fatalf("Unmarshalled null Time must be valid, but was %v", value.Value) | ||
} | ||
|
||
str = `{"value": null}` | ||
|
||
if err := json.Unmarshal([]byte(str), &value); err != nil { | ||
t.Fatalf("Time must be unmarshalled to null, but was %v", err) | ||
} | ||
|
||
if value.Value.Valid { | ||
t.Fatal("Unmarshalled null Time must be invalid") | ||
} | ||
} | ||
|
||
func TestGettersSettersTime(t *testing.T) { | ||
value := NewTime(time.Now(), true) | ||
value.SetNil() | ||
|
||
if !value.Time.Equal(time.Time{}) || value.Valid { | ||
t.Fatal("Time must be nil") | ||
} | ||
|
||
value.SetValid(time.Now()) | ||
|
||
if value.Time.Equal(time.Time{}) || !value.Valid { | ||
t.Fatal("Time must be valid") | ||
} | ||
} |