github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/commons/times/date.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package times 19 20 import ( 21 "database/sql/driver" 22 "fmt" 23 "reflect" 24 "time" 25 ) 26 27 func DateNow() Date { 28 return DataOf(time.Now()) 29 } 30 31 func NewDate(year int, month time.Month, day int) Date { 32 return Date{ 33 Year: year, 34 Month: month, 35 Day: day, 36 } 37 } 38 39 func DataOf(t time.Time) Date { 40 return NewDate(t.Year(), t.Month(), t.Day()) 41 } 42 43 type Date struct { 44 Year int 45 Month time.Month 46 Day int 47 } 48 49 func (d *Date) UnmarshalJSON(p []byte) error { 50 if p == nil || len(p) < 3 { 51 return nil 52 } 53 p = p[1 : len(p)-1] 54 v, parseErr := time.Parse(time.DateOnly, string(p)) 55 if parseErr != nil { 56 return fmt.Errorf("unmarshal %s failed, layout of date must be 2006-01-02, %v", string(p), parseErr) 57 } 58 d.Year = v.Year() 59 d.Month = v.Month() 60 d.Day = v.Day() 61 return nil 62 } 63 64 func (d Date) MarshalJSON() ([]byte, error) { 65 return []byte(fmt.Sprintf("\"%s\"", d.ToTime().Format(time.DateOnly))), nil 66 } 67 68 func (d Date) ToTime() time.Time { 69 if d.Year < 1 { 70 d.Year = 1 71 } 72 if d.Month < 1 { 73 d.Month = 1 74 } 75 if d.Day < 1 { 76 d.Day = 1 77 } 78 return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, time.Local) 79 } 80 81 func (d Date) IsZero() (ok bool) { 82 ok = d.Year < 2 && d.Month < 2 && d.Day < 2 83 return 84 } 85 86 func (d Date) String() string { 87 return d.ToTime().Format(time.DateOnly) 88 } 89 90 func (d *Date) Scan(src interface{}) error { 91 if src == nil { 92 return nil 93 } 94 x := "" 95 switch src.(type) { 96 case string: 97 x = src.(string) 98 case []byte: 99 x = string(src.([]byte)) 100 case time.Time: 101 v := src.(time.Time) 102 d.Year = v.Year() 103 d.Month = v.Month() 104 d.Day = v.Day() 105 return nil 106 default: 107 return fmt.Errorf("fns: scan date raw value failed for %v is not supported", reflect.TypeOf(src).String()) 108 } 109 if x == "" { 110 return nil 111 } 112 v, parseErr := time.Parse(time.DateOnly, x) 113 if parseErr != nil { 114 return fmt.Errorf("fns: scan date value failed, parse %s failed, %v", x, parseErr) 115 } 116 d.Year = v.Year() 117 d.Month = v.Month() 118 d.Day = v.Day() 119 return nil 120 } 121 122 func (d Date) Value() (driver.Value, error) { 123 if d.IsZero() { 124 return nil, nil 125 } 126 return d.String(), nil 127 }