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  }