1+ package mssql
2+
3+ import (
4+ "database/sql/driver"
5+ "encoding/json"
6+ "fmt"
7+ "time"
8+
9+ "github.com/golang-sql/civil"
10+ )
11+
12+ // NullDate represents a civil.Date that may be null.
13+ // NullDate implements the Scanner interface so it can be used as a scan destination,
14+ // similar to sql.NullString.
15+ type NullDate struct {
16+ Date civil.Date
17+ Valid bool // Valid is true if Date is not NULL
18+ }
19+
20+ // Scan implements the Scanner interface.
21+ func (n * NullDate ) Scan (value interface {}) error {
22+ if value == nil {
23+ n .Date , n .Valid = civil.Date {}, false
24+ return nil
25+ }
26+ n .Valid = true
27+ switch v := value .(type ) {
28+ case time.Time :
29+ n .Date = civil .DateOf (v )
30+ return nil
31+ default :
32+ n .Valid = false
33+ return fmt .Errorf ("cannot scan %T into NullDate" , value )
34+ }
35+ }
36+
37+ // Value implements the driver Valuer interface.
38+ func (n NullDate ) Value () (driver.Value , error ) {
39+ if ! n .Valid {
40+ return nil , nil
41+ }
42+ return n .Date , nil
43+ }
44+
45+ // String returns the string representation of the date or "NULL".
46+ func (n NullDate ) String () string {
47+ if ! n .Valid {
48+ return "NULL"
49+ }
50+ return n .Date .String ()
51+ }
52+
53+ // MarshalText implements the encoding.TextMarshaler interface.
54+ func (n NullDate ) MarshalText () ([]byte , error ) {
55+ if ! n .Valid {
56+ return []byte ("null" ), nil
57+ }
58+ return n .Date .MarshalText ()
59+ }
60+
61+ // UnmarshalJSON implements the json.Unmarshaler interface.
62+ func (n * NullDate ) UnmarshalJSON (b []byte ) error {
63+ if string (b ) == "null" {
64+ n .Date , n .Valid = civil.Date {}, false
65+ return nil
66+ }
67+ err := json .Unmarshal (b , & n .Date )
68+ n .Valid = err == nil
69+ return err
70+ }
71+
72+ // MarshalJSON implements the json.Marshaler interface.
73+ func (n NullDate ) MarshalJSON () ([]byte , error ) {
74+ if ! n .Valid {
75+ return []byte ("null" ), nil
76+ }
77+ return json .Marshal (n .Date )
78+ }
79+
80+ // NullDateTime represents a civil.DateTime that may be null.
81+ // NullDateTime implements the Scanner interface so it can be used as a scan destination,
82+ // similar to sql.NullString.
83+ type NullDateTime struct {
84+ DateTime civil.DateTime
85+ Valid bool // Valid is true if DateTime is not NULL
86+ }
87+
88+ // Scan implements the Scanner interface.
89+ func (n * NullDateTime ) Scan (value interface {}) error {
90+ if value == nil {
91+ n .DateTime , n .Valid = civil.DateTime {}, false
92+ return nil
93+ }
94+ n .Valid = true
95+ switch v := value .(type ) {
96+ case time.Time :
97+ n .DateTime = civil .DateTimeOf (v )
98+ return nil
99+ default :
100+ n .Valid = false
101+ return fmt .Errorf ("cannot scan %T into NullDateTime" , value )
102+ }
103+ }
104+
105+ // Value implements the driver Valuer interface.
106+ func (n NullDateTime ) Value () (driver.Value , error ) {
107+ if ! n .Valid {
108+ return nil , nil
109+ }
110+ return n .DateTime , nil
111+ }
112+
113+ // String returns the string representation of the datetime or "NULL".
114+ func (n NullDateTime ) String () string {
115+ if ! n .Valid {
116+ return "NULL"
117+ }
118+ return n .DateTime .String ()
119+ }
120+
121+ // MarshalText implements the encoding.TextMarshaler interface.
122+ func (n NullDateTime ) MarshalText () ([]byte , error ) {
123+ if ! n .Valid {
124+ return []byte ("null" ), nil
125+ }
126+ return n .DateTime .MarshalText ()
127+ }
128+
129+ // UnmarshalJSON implements the json.Unmarshaler interface.
130+ func (n * NullDateTime ) UnmarshalJSON (b []byte ) error {
131+ if string (b ) == "null" {
132+ n .DateTime , n .Valid = civil.DateTime {}, false
133+ return nil
134+ }
135+ err := json .Unmarshal (b , & n .DateTime )
136+ n .Valid = err == nil
137+ return err
138+ }
139+
140+ // MarshalJSON implements the json.Marshaler interface.
141+ func (n NullDateTime ) MarshalJSON () ([]byte , error ) {
142+ if ! n .Valid {
143+ return []byte ("null" ), nil
144+ }
145+ return json .Marshal (n .DateTime )
146+ }
147+
148+ // NullTime represents a civil.Time that may be null.
149+ // NullTime implements the Scanner interface so it can be used as a scan destination,
150+ // similar to sql.NullString.
151+ type NullTime struct {
152+ Time civil.Time
153+ Valid bool // Valid is true if Time is not NULL
154+ }
155+
156+ // Scan implements the Scanner interface.
157+ func (n * NullTime ) Scan (value interface {}) error {
158+ if value == nil {
159+ n .Time , n .Valid = civil.Time {}, false
160+ return nil
161+ }
162+ n .Valid = true
163+ switch v := value .(type ) {
164+ case time.Time :
165+ n .Time = civil .TimeOf (v )
166+ return nil
167+ default :
168+ n .Valid = false
169+ return fmt .Errorf ("cannot scan %T into NullTime" , value )
170+ }
171+ }
172+
173+ // Value implements the driver Valuer interface.
174+ func (n NullTime ) Value () (driver.Value , error ) {
175+ if ! n .Valid {
176+ return nil , nil
177+ }
178+ return n .Time , nil
179+ }
180+
181+ // String returns the string representation of the time or "NULL".
182+ func (n NullTime ) String () string {
183+ if ! n .Valid {
184+ return "NULL"
185+ }
186+ return n .Time .String ()
187+ }
188+
189+ // MarshalText implements the encoding.TextMarshaler interface.
190+ func (n NullTime ) MarshalText () ([]byte , error ) {
191+ if ! n .Valid {
192+ return []byte ("null" ), nil
193+ }
194+ return n .Time .MarshalText ()
195+ }
196+
197+ // UnmarshalJSON implements the json.Unmarshaler interface.
198+ func (n * NullTime ) UnmarshalJSON (b []byte ) error {
199+ if string (b ) == "null" {
200+ n .Time , n .Valid = civil.Time {}, false
201+ return nil
202+ }
203+ err := json .Unmarshal (b , & n .Time )
204+ n .Valid = err == nil
205+ return err
206+ }
207+
208+ // MarshalJSON implements the json.Marshaler interface.
209+ func (n NullTime ) MarshalJSON () ([]byte , error ) {
210+ if ! n .Valid {
211+ return []byte ("null" ), nil
212+ }
213+ return json .Marshal (n .Time )
214+ }
0 commit comments