github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/offset_date_time.go (about) 1 package chrono 2 3 import ( 4 "math/big" 5 ) 6 7 // OffsetDateTime has the same semantics as LocalDateTime, but with the addition of a timezone offset. 8 type OffsetDateTime struct { 9 v big.Int 10 o int64 11 } 12 13 // OffsetDateTimeOf returns an OffsetDateTime that represents the specified year, month, day, 14 // hour, minute, second, and nanosecond offset within the specified second. 15 // The supplied offset is applied to the returned OffsetDateTime in the same manner as OffsetOf. 16 // The same range of values as supported by OfLocalDate and OfLocalTime are allowed here. 17 func OffsetDateTimeOf(year int, month Month, day, hour, min, sec, nsec, offsetHours, offsetMins int) OffsetDateTime { 18 date, err := makeDate(year, int(month), day) 19 if err != nil { 20 panic(err.Error()) 21 } 22 23 time, err := makeTime(hour, min, sec, nsec) 24 if err != nil { 25 panic(err.Error()) 26 } 27 28 return OffsetDateTime{ 29 v: makeDateTime(date, time), 30 o: makeOffset(offsetHours, offsetMins), 31 } 32 } 33 34 // OfLocalDateOffsetTime combines a LocalDate and OffsetTime into an OffsetDateTime. 35 func OfLocalDateOffsetTime(date LocalDate, time OffsetTime) OffsetDateTime { 36 return OffsetDateTime{ 37 v: makeDateTime(int64(date), time.v), 38 o: time.o, 39 } 40 } 41 42 // OfLocalDateTimeOffset combines a LocalDate, LocalTime, and Offset into an OffsetDateTime. 43 func OfLocalDateTimeOffset(date LocalDate, time LocalTime, offset Extent) OffsetDateTime { 44 return OffsetDateTime{ 45 v: makeDateTime(int64(date), time.v), 46 o: int64(offset), 47 } 48 } 49 50 // Compare compares d with d2. If d is before d2, it returns -1; 51 // if d is after d2, it returns 1; if they're the same, it returns 0. 52 func (d OffsetDateTime) Compare(d2 OffsetDateTime) int { 53 return d.v.Cmp(&d2.v) 54 } 55 56 // Offset returns the offset of d. 57 func (d OffsetDateTime) Offset() Offset { 58 return Offset(d.o) 59 } 60 61 // Split returns separate a LocalDate and OffsetTime that together represent d. 62 func (d OffsetDateTime) Split() (LocalDate, OffsetTime) { 63 date, time := splitDateAndTime(d.v) 64 return LocalDate(date), OffsetTime{v: time, o: d.o} 65 } 66 67 // In returns a copy of t, adjusted to the supplied offset. 68 func (d OffsetDateTime) In(offset Offset) OffsetDateTime { 69 return OffsetDateTime{ 70 v: bigDateToOffset(d.v, d.o, int64(offset)), 71 o: int64(offset), 72 } 73 } 74 75 // UTC is a shortcut for t.In(UTC). 76 func (d OffsetDateTime) UTC() OffsetDateTime { 77 return OffsetDateTime{v: bigDateToOffset(d.v, d.o, 0)} 78 } 79 80 // Local returns the LocalDateTime represented by d. 81 func (d OffsetDateTime) Local() LocalDateTime { 82 return LocalDateTime{d.v} 83 } 84 85 // Add returns the datetime d+v. 86 // This function panics if the resulting datetime would fall outside of the allowed range. 87 func (d OffsetDateTime) Add(v Duration) OffsetDateTime { 88 out, err := addDurationToBigDate(d.v, v) 89 if err != nil { 90 panic(err.Error()) 91 } 92 return OffsetDateTime{v: out, o: d.o} 93 } 94 95 // CanAdd returns false if Add would panic if passed the same arguments. 96 func (d OffsetDateTime) CanAdd(v Duration) bool { 97 _, err := addDurationToBigDate(d.v, v) 98 return err == nil 99 } 100 101 // AddDate returns the datetime corresponding to adding the given number of years, months, and days to d. 102 // This function panic if the resulting datetime would fall outside of the allowed date range. 103 func (d OffsetDateTime) AddDate(years, months, days int) OffsetDateTime { 104 out, err := addDateToBigDate(d.v, years, months, days) 105 if err != nil { 106 panic(err.Error()) 107 } 108 return OffsetDateTime{v: out, o: d.o} 109 } 110 111 // CanAddDate returns false if AddDate would panic if passed the same arguments. 112 func (d OffsetDateTime) CanAddDate(years, months, days int) bool { 113 _, err := addDateToBigDate(d.v, years, months, days) 114 return err == nil 115 } 116 117 // Sub returns the duration d-u. 118 func (d OffsetDateTime) Sub(u OffsetDateTime) Duration { 119 out := new(big.Int).Set(&d.v) 120 out.Add(out, big.NewInt(d.o)) 121 out.Sub(out, &u.v) 122 out.Sub(out, big.NewInt(u.o)) 123 return Duration{v: *out} 124 } 125 126 func (d OffsetDateTime) String() string { 127 date, time := splitDateAndTime(d.v) 128 hour, min, sec, nsec := fromTime(time) 129 year, month, day, err := fromDate(date) 130 if err != nil { 131 panic(err.Error()) 132 } 133 return simpleDateStr(year, month, day) + " " + simpleTimeStr(hour, min, sec, nsec, &d.o) 134 } 135 136 // Format returns a textual representation of the date-time value formatted according to the layout defined by the argument. 137 // See the constants section of the documentation to see how to represent the layout format. 138 func (d OffsetDateTime) Format(layout string) string { 139 date, time := d.Split() 140 out, err := formatDateTimeOffset(layout, (*int32)(&date), &time.v, &d.o) 141 if err != nil { 142 panic(err.Error()) 143 } 144 return out 145 } 146 147 // Parse a formatted string and store the value it represents in d. 148 // See the constants section of the documentation to see how to represent the layout format. 149 func (d *OffsetDateTime) Parse(layout, value string) error { 150 dv, tv := splitDateAndTime(d.v) 151 var ov int64 152 if err := parseDateAndTime(layout, value, &dv, &tv, &ov); err != nil { 153 return err 154 } 155 156 d.v = makeDateTime(dv, tv) 157 d.o = ov 158 return nil 159 }