134 lines
3.2 KiB
Go
134 lines
3.2 KiB
Go
package datetime
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
type integer interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64
|
|
}
|
|
|
|
type uinteger interface {
|
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
|
}
|
|
|
|
type float interface {
|
|
~float32 | ~float64
|
|
}
|
|
|
|
type number interface {
|
|
integer | uinteger | float
|
|
}
|
|
|
|
func cmp[N number](n1, n2 N) int {
|
|
switch {
|
|
case n1 < n2:
|
|
return -1
|
|
case n1 == n2:
|
|
return 0
|
|
default:
|
|
return 1
|
|
}
|
|
}
|
|
func abs[N integer | float](n N) N {
|
|
if n < 0 {
|
|
return -n
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func spl[N integer | uinteger](e []N, n int) (ed, ec []N) {
|
|
ed = e
|
|
if len(e) > n {
|
|
ed, ec = e[:n], e[n:]
|
|
}
|
|
return
|
|
}
|
|
|
|
func bissextil(y int) bool { return y%4 == 0 && !(y%100 == 0 && y%400 != 0) }
|
|
func monthLen(y int, m uint) uint {
|
|
switch m {
|
|
case February:
|
|
if bissextil(y) {
|
|
return 29
|
|
}
|
|
return 28
|
|
case April, June, September, November:
|
|
return 30
|
|
case January, March, May, July, August, October, December:
|
|
return 31
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
func yearLen(y int) uint {
|
|
if bissextil(y) {
|
|
return 366
|
|
}
|
|
return 365
|
|
}
|
|
|
|
func sit(h, i uint, args ...uint) float64 {
|
|
var s, v uint
|
|
if len(args) > 0 {
|
|
s = args[0]
|
|
if len(args) > 1 {
|
|
v = args[1]
|
|
}
|
|
}
|
|
v += s*MillisecondPerSecond + i*MillisecondPerMinute + h*MillisecondPerHour
|
|
return float64(v) * float64(BeatPerDay) / float64(MillisecondPerDay)
|
|
}
|
|
|
|
func timezone(tz ...string) *time.Location {
|
|
if len(tz) > 0 {
|
|
if l, err := time.LoadLocation(tz[0]); err == nil {
|
|
return l
|
|
}
|
|
}
|
|
return DefaultTZ
|
|
}
|
|
func toTZ(t time.Time, tz ...string) time.Time { return t.In(timezone(tz...)) }
|
|
func now(tz ...string) time.Time { return toTZ(time.Now(), tz...) }
|
|
func yesterday(tz ...string) time.Time { return now(tz...).AddDate(0, 0, -1) }
|
|
func tomorrow(tz ...string) time.Time { return now(tz...).AddDate(0, 0, 1) }
|
|
|
|
func fromDT(y int, m, d, h, i, s, v uint, l *time.Location) time.Time {
|
|
return time.Date(y, time.Month(m-1), int(d), int(h), int(i), int(s), int(d*NanosecondPerMillisecond), l)
|
|
}
|
|
func fromD(y int, m, d uint, l *time.Location) time.Time { return fromDT(y, m, d, 0, 0, 0, 0, l) }
|
|
func fromT(h, i, s, v uint, l *time.Location) time.Time {
|
|
t := now().In(l)
|
|
y, m, d := t.Year(), uint(t.Month()-1), uint(t.Day())
|
|
return fromDT(y, m, d, h, i, s, v, l)
|
|
}
|
|
|
|
// Clock
|
|
func formatC(h, i uint, args ...uint) (uint, uint, uint, uint, Precision) {
|
|
l := len(args)
|
|
p, s, v := PrecisionMinute-Precision(l), uint(0), uint(0)
|
|
if l > 0 {
|
|
s = args[0]
|
|
if l > 1 {
|
|
v = args[1]
|
|
}
|
|
}
|
|
return h, i, s, v, p
|
|
}
|
|
func ms(h, i, s, n uint) uint {
|
|
return h*MillisecondPerHour + i*MillisecondPerMinute + s*MillisecondPerSecond + n
|
|
}
|
|
|
|
// Date
|
|
func validM(m uint) bool { return m >= January && m <= December }
|
|
func validD(y int, m, d uint) bool { return validM(m) && d > 0 && d < monthLen(y, m) }
|
|
func getD[N integer | uinteger](d date, t string) N { return N((d & maskDate[t]) >> shiftDate[t]) }
|
|
func setD[N integer | uinteger](e N, t string) date { return date(e<<shiftDate[t]) & maskDate[t] }
|
|
func replD[N integer | uinteger](d date, e N, t string) date {
|
|
return (d & ^maskDate[t]) | setD(e, t)
|
|
}
|
|
|
|
func diffBow(d uint) int { return int(Monday) - ((int(d) + DayPerWeek) % DayPerWeek) }
|
|
func diffEow(d uint) int { return DayPerWeek - ((int(d) + DayPerWeek) % DayPerWeek) }
|