github.com/go-chrono/chrono@v0.0.0-20240102183611-532f0d0d7c34/offset.go (about)

     1  package chrono
     2  
     3  import "fmt"
     4  
     5  // UTC represents Universal Coordinated Time (UTC).
     6  const UTC = Offset(0)
     7  
     8  // Offset represents a time zone offset from UTC with precision to the minute.
     9  type Offset Extent
    10  
    11  // OffsetOf returns the Offset represented by a number of hours and minutes.
    12  // If hours is non-zero, the sign of minutes is ignored, e.g.:
    13  //   - OffsetOf(-2, 30) = -02h:30m
    14  //   - OffsetOf(2, -30) = 02h:30m
    15  //   - OffsetOf(0, 30) = 00h:30m
    16  //   - OffsetOf(0, -30) = -00h:30m
    17  func OffsetOf(hours, mins int) Offset {
    18  	return Offset(makeOffset(hours, mins))
    19  }
    20  
    21  func makeOffset(hours, mins int) int64 {
    22  	if hours == 0 {
    23  		return int64(mins) * oneMinute
    24  	}
    25  
    26  	if mins < 0 {
    27  		mins = -mins
    28  	}
    29  
    30  	if hours < 0 {
    31  		return (int64(hours) * oneHour) - (int64(mins) * oneMinute)
    32  	}
    33  	return (int64(hours) * oneHour) + (int64(mins) * oneMinute)
    34  }
    35  
    36  // String returns the time zone designator according to ISO 8601, truncating first to the minute.
    37  // If o == 0, String returns "Z" for the UTC offset.
    38  // In all other cases, a string in the format of ±hh:mm is returned.
    39  // Note that the sign and number of minutes is always included, even if 0.
    40  func (o Offset) String() string {
    41  	return offsetString(int64(o), ":")
    42  }
    43  
    44  func offsetString(o int64, sep string) string {
    45  	e := truncateExtent(o, oneMinute)
    46  	if e == 0 {
    47  		return "Z"
    48  	}
    49  
    50  	sign := "+"
    51  	if e < 0 {
    52  		sign = "-"
    53  	}
    54  
    55  	hours, mins, _, _ := extentUnits(extentAbs(e))
    56  	return fmt.Sprintf("%s%02d%s%02d", sign, hours, sep, mins)
    57  }