gob/datetime/datetime.go

523 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package datetime
import (
"time"
)
type datetime struct {
date
clock clock
}
func newDT(d date, c clock) datetime {
if d.valid() && c.valid() {
return datetime{d, c}
}
return datetime{dateNil, clockNil}
}
func (dt datetime) h() uint { return dt.clock.h() }
func (dt datetime) i() uint { return dt.clock.i() }
func (dt datetime) s() uint { return dt.clock.s() }
func (dt datetime) v() uint { return dt.clock.v() }
func (dt datetime) p() Precision { return dt.clock.p() }
func (dt datetime) dv() uint { return dt.clock.dv() }
func (dt datetime) ds() uint { return dt.clock.ds() }
func (dt datetime) di() uint { return dt.clock.di() }
func (dt datetime) t(l *time.Location) time.Time {
return fromDT(dt.y(), dt.m(), dt.d(), dt.h(), dt.i(), dt.s(), dt.v(), l)
}
func (dt datetime) dst(l *time.Location) bool { return dt.t(l).IsDST() }
func (dt datetime) ts(l *time.Location) int64 { return dt.t(l).Unix() }
func (dt datetime) tv(l *time.Location) int64 { return dt.t(l).UnixMilli() }
func (dt datetime) valid() bool { return dt.date.valid() && dt.clock.valid() }
func (dt datetime) setY(y int, e ...uint) datetime {
ed, ec := spl(e, 2)
d, c := dt.date.setY(y, ed...), dt.clock
if len(ec) > 0 {
c = c.setH(ec[0], ec[1:]...)
}
return newDT(d, c)
}
func (dt datetime) setM(m uint, e ...uint) datetime {
ed, ec := spl(e, 1)
d, c := dt.date.setM(m, ed...), dt.clock
if len(ec) > 0 {
c = c.setH(ec[0], ec[1:]...)
}
return newDT(d, c)
}
func (dt datetime) setD(d uint, e ...uint) datetime {
t, c := dt.date.setD(d), dt.clock
if len(e) > 0 {
c = c.setH(e[0], e[1:]...)
}
return newDT(t, c)
}
func (dt datetime) setH(h uint, e ...uint) datetime { return newDT(dt.date, dt.clock.setH(h, e...)) }
func (dt datetime) setI(i uint, e ...uint) datetime { return newDT(dt.date, dt.clock.setI(i, e...)) }
func (dt datetime) setS(s uint, e ...uint) datetime { return newDT(dt.date, dt.clock.setS(s, e...)) }
func (dt datetime) setV(v uint) datetime { return newDT(dt.date, dt.clock.setV(v)) }
func (dt datetime) setP(p Precision) datetime { return newDT(dt.date, dt.clock.setP(p)) }
func (dt datetime) add(y, m, d, h, i int, e ...int) datetime {
if !dt.valid() {
return dt
}
p := dt.p()
v := int(dt.dv()) + h*MillisecondPerHour + i*MillisecondPerMinute
if len(e) > 0 {
p, v = min(p, PrecisionSecond), v+e[0]*MillisecondPerSecond
if len(e) > 1 {
p, v = PrecisionMillisecond, v+e[1]
}
}
dc := v / MillisecondPerDay
d, v = d+dc, v-dc*MillisecondPerDay
return newDT(dt.date.add(y, m, d), newC(uint(v), p))
}
func (dt datetime) addT(y, m, d int) datetime { return newDT(dt.date.add(y, m, d), dt.clock) }
func (dt datetime) addC(h, i int, e ...int) datetime { return dt.add(0, 0, 0, h, i, e...) }
func (dt datetime) addY(y int) datetime { return dt.addT(y, 0, 0) }
func (dt datetime) addM(m int) datetime { return dt.addT(0, m, 0) }
func (dt datetime) addW(w int) datetime { return dt.addD(w * DayPerWeek) }
func (dt datetime) addD(d int) datetime { return dt.addT(0, 0, d) }
func (dt datetime) addH(h int) datetime { return dt.addC(h, 0) }
func (dt datetime) addI(i int) datetime { return dt.addC(0, i) }
func (dt datetime) addS(s int) datetime { return dt.addC(0, 0, s) }
func (dt datetime) addV(n int) datetime { return dt.addC(0, 0, 0, n) }
func (dt datetime) addDD(dd Duration) datetime {
f := map[Unit]func(int) datetime{
Year: dt.addY,
Month: dt.addM,
Week: dt.addW,
Day: dt.addD,
Hour: dt.addH,
Minute: dt.addI,
Second: dt.addS,
Millisecond: dt.addV,
}
e, u := dd.Value(), dd.Unit()
if cb, ok := f[u]; ok {
return cb(e)
}
return dt
}
func (dt datetime) bY() datetime { return dt.setM(January, 1).bD() }
func (dt datetime) eY() datetime { return dt.setM(December, 31).eD() }
func (dt datetime) bM() datetime { return dt.setD(1).bD() }
func (dt datetime) eM() datetime { return dt.setD(monthLen(dt.y(), dt.m())).eD() }
func (dt datetime) bW(l *time.Location) datetime { return newDT(dt.date.bW(l), dt.clock).bD() }
func (dt datetime) eW(l *time.Location) datetime { return newDT(dt.date.eW(l), dt.clock).eD() }
func (dt datetime) bD() datetime { return newDT(dt.date, dt.clock.bD()) }
func (dt datetime) eD() datetime { return newDT(dt.date, dt.clock.eD()) }
func (dt datetime) bH() datetime { return newDT(dt.date, dt.clock.bH()) }
func (dt datetime) eH() datetime { return newDT(dt.date, dt.clock.eH()) }
func (dt datetime) bI() datetime { return newDT(dt.date, dt.clock.bI()) }
func (dt datetime) eI() datetime { return newDT(dt.date, dt.clock.eI()) }
func (dt datetime) bS() datetime { return newDT(dt.date, dt.clock.bS()) }
func (dt datetime) eS() datetime { return newDT(dt.date, dt.clock.eS()) }
func (dt1 datetime) cmp(dt2 datetime) int {
if !dt1.valid() {
if !dt2.valid() {
return 0
}
return -1
}
if !dt2.valid() {
return 1
}
if c := dt1.date.cmp(dt2.date); c != 0 {
return c
}
return dt1.clock.cmp(dt2.clock)
}
func (dt1 datetime) subV(dt2 datetime, l1, l2 *time.Location) int {
return int(dt1.tv(l1) - dt2.tv(l2))
}
func (dt1 datetime) subS(dt2 datetime, l1, l2 *time.Location) int {
return dt1.subV(dt2, l1, l2) / MillisecondPerSecond
}
func (dt1 datetime) subI(dt2 datetime, l1, l2 *time.Location) int {
return dt1.subV(dt2, l1, l2) / MillisecondPerMinute
}
func (dt1 datetime) subH(dt2 datetime, l1, l2 *time.Location) int {
return dt1.subV(dt2, l1, l2) / MillisecondPerHour
}
func (dt1 datetime) subD(dt2 datetime, l1, l2 *time.Location) int {
return dt1.subV(dt2, l1, l2) / MillisecondPerMinute
}
func (dt1 datetime) subW(dt2 datetime, l1, l2 *time.Location) int {
return dt1.subV(dt2, l1, l2) / MillisecondPerWeek
}
func (dt1 datetime) subM(dt2 datetime) int {
d := dt1.date.subM(dt2.date)
if d < 0 {
dd, dv := int(dt1.d())-int(dt2.d()), int(dt1.dv())-int(dt2.dv())
if dd > 0 || (dd == 0 && dv > 0) {
d++
}
}
return d
}
func (dt1 datetime) subY(dt2 datetime) int { return dt1.subM(dt2) / MonthPerYear }
func (dt datetime) f(f string, l *time.Location) string {
if !dt.valid() {
return "-"
}
return formatT(dt.t(l), f)
}
func (dt datetime) str(l *time.Location) string { return dt.f("Y-m-d", l) }
// DateTime représente une indication de temps.
type DateTime struct {
datetime
location *time.Location
}
// DateTimeNil retourne un temps nul.
func DateTimeNil() (dt DateTime) { return }
func initDT0(d date, c clock, l *time.Location) DateTime { return initDT(newDT(d, c), l) }
func initDT(dt datetime, l *time.Location) DateTime {
if !dt.valid() {
return DateTimeNil()
}
return DateTime{dt, l}
}
// NewDateTime retourne un temps dans le fuseau horaire par défaut.
// La précision est calculée automatiquement suivant que la seconde et la milliseconde sont indiquées.
func NewDateTime(y int, m, d, h, i uint, args ...uint) DateTime {
return initDT0(newD(y, m, d), newC0(h, i, args...), DefaultTZ)
}
// NewDateTimeTZ agit comme NewDateTime mais dans le fuseau horaire tz.
func NewDateTimeTZ(tz string, y int, m, d, h, i uint, args ...uint) DateTime {
dt := NewDateTime(y, m, d, h, m, args...)
if dt.valid() {
dt.location = timezone(tz)
}
return dt
}
// NewDateTimeFromTime retourne le temps à partir dune date Go.
func NewDateTimeFromTime(t time.Time, p ...Precision) DateTime {
var (
pp = PrecisionMillisecond
y, m, d = t.Date()
h, i, s = t.Clock()
v = t.Nanosecond() / NanosecondPerMillisecond
l = t.Location()
)
if len(p) > 0 {
pp = p[0]
}
return initDT0(newD(y, uint(m+1), uint(d)), newC(ms(uint(h), uint(i), uint(s), uint(v)), pp), l)
}
// DateTimeNow retourne la date actuelle. Si tz est renseignée,
// la date est placée dans le fuseau horaire indiqué.
func DateTimeNow(p Precision, tz ...string) DateTime {
return NewDateTimeFromTime(now(tz...), p)
}
func (dt DateTime) Now() DateTime { return DateTimeNow(dt.p(), dt.location.String()) }
// DateTimeGuess retourne la date à partir de e en essayant de deviner le format.
func DateTimeGuess(p Precision, e string, tz ...string) DateTime {
if t, ok := guess(e, tz...).Get(); ok {
return NewDateTimeFromTime(t, p)
}
return DateTimeNil()
}
// DateTimeParse retourne la date à partir de e en spécifiant le format f.
func DateTimeParse(p Precision, e, f string, tz ...string) DateTime {
if t, ok := parse(e, f, tz...).Get(); ok {
return NewDateTimeFromTime(t, p)
}
return DateTimeNil()
}
// Precision retourne la précision de lheure.
func (dt DateTime) Precision() Precision { return dt.p() }
// IsNil retourne vrai si la date est nulle.
func (dt DateTime) IsNil() bool { return !dt.valid() }
// Year retourne lannée.
func (dt DateTime) Year() int { return dt.y() }
// Month retourne le mois.
func (dt DateTime) Month() uint { return dt.m() }
// Day retourne le .
func (dt DateTime) Day() uint { return dt.d() }
// Hour retourne lheure.
func (dt DateTime) Hour() uint { return dt.h() }
// Minute retourne la minute.
func (dt DateTime) Minute() uint { return dt.i() }
// Second retourne la seconde.
func (dt DateTime) Second() uint { return dt.s() }
// Milli retourne la milliseconde.
func (dt DateTime) Milli() uint { return dt.v() }
// Date retourne la partie date.
func (dt DateTime) Date() (y int, m, d uint) { return dt.y(), dt.m(), dt.d() }
// Clock retourne la partie horaire.
func (dt DateTime) Clock() (h, i, s, v uint) { return dt.h(), dt.i(), dt.s(), dt.m() }
// YearDay retourne le jour dans lannée (de 1 à 366).
func (dt DateTime) YeardDay() uint { return dt.yd() }
// WeekDay retourne le jour dans la semaine (de 0 à 6 en commençant par dimanche).
func (dt DateTime) WeekDay() uint { return dt.wd(dt.location) }
// IsBissextil retourne vrai si la date est dans une année bissextile.
func (dt DateTime) IsBissextile() bool { return dt.b() }
// DaysInYear retourne le nombre de jours dans lannée.
func (dt DateTime) DaysInYear() uint { return dt.yl() }
// DaysInMonth retourne le nombre de jours dans le mois.
func (dt DateTime) DaysInMonth() uint { return dt.ml() }
// DayMinute retourne le nombre de minutes écoulées dans la journée.
func (dt DateTime) DayMinute() uint { return dt.di() }
// DaySecond retourne le nombre de secondes écoulées dans la journée.
func (dt DateTime) DaySecond() uint { return dt.ds() }
// DayMilli retourne le nombre de millisecondes écoulées dans la journée.
func (dt DateTime) DayMilli() uint { return dt.dv() }
// ToDate convertit le temps en ne conservant que la partie date.
func (dt DateTime) ToDate() Date { return newDate(dt.date, dt.location) }
// ToClock convertit le temps en ne conservant que la partie heure.
func (dt DateTime) ToClock() Clock { return newClock(dt.clock, dt.location) }
// ToDateClock sépare la partie date et la partie heure.
func (dt DateTime) ToDateClock() (Date, Clock) { return dt.ToDate(), dt.ToClock() }
// SetYear modifie lannée.
func (dt DateTime) SetYear(y int, args ...uint) DateTime {
return initDT(dt.setY(y, args...), dt.location)
}
// SetMonth modifie le mois.
func (dt DateTime) SetMonth(m uint, args ...uint) DateTime {
return initDT(dt.setM(m, args...), dt.location)
}
// SetDay modifie le jour.
func (dt DateTime) SetDay(d uint, args ...uint) DateTime {
return initDT(dt.setD(d, args...), dt.location)
}
// SetHour modifie lheure.
func (dt DateTime) SetHour(h uint, args ...uint) DateTime {
return initDT(dt.setH(h, args...), dt.location)
}
// SetMinute modifie la minute.
func (dt DateTime) SetMinute(i uint, args ...uint) DateTime {
return initDT(dt.setI(i, args...), dt.location)
}
// SetSecond modifie la seconde.
func (dt DateTime) SetSecond(s uint, args ...uint) DateTime {
return initDT(dt.setS(s, args...), dt.location)
}
// SetMilli modifie la milliseconde.
func (dt DateTime) SetMilli(v uint) DateTime { return initDT(dt.setV(v), dt.location) }
// SetPrecision modifie la précision.
func (dt DateTime) SetPrecision(p Precision) DateTime { return initDT(dt.setP(p), dt.location) }
// Add incrémente lannée, le mois, le jour, lheure, la minute,
// et facultativement la seconde et la milliseconde.
func (dt DateTime) Add(y, m, d, h, i int, args ...int) DateTime {
return initDT(dt.add(y, m, d, h, i, args...), dt.location)
}
// AddDate incrémente lannée, le mois et le jour.
func (dt DateTime) AddDate(y, m, d int) DateTime { return initDT(dt.addT(y, m, d), dt.location) }
// AddClock incrémente lheure, la minute et facultativement la seconde et la milliseconde.
func (dt DateTime) AddClock(h, i int, args ...int) DateTime {
return initDT(dt.addC(h, i, args...), dt.location)
}
// AddYear incrémente lannée.
func (dt DateTime) AddYear(y int) DateTime { return initDT(dt.addY(y), dt.location) }
// AddMonth incrémente le mois.
func (dt DateTime) AddMonth(m int) DateTime { return initDT(dt.addM(m), dt.location) }
// AddWeek incrémente la semaine.
func (dt DateTime) AddWeek(w int) DateTime { return initDT(dt.addW(w), dt.location) }
// AddDay incrémente le jour.
func (dt DateTime) AddDay(d int) DateTime { return initDT(dt.addD(d), dt.location) }
// AddHour incrémente lheure.
func (dt DateTime) AddHour(h int) DateTime { return initDT(dt.addH(h), dt.location) }
// AddMinute incrémente la minute.
func (dt DateTime) AddMinute(i int) DateTime { return initDT(dt.addI(i), dt.location) }
// AddSecond incrémente la seconde.
func (dt DateTime) AddSecond(s int) DateTime { return initDT(dt.addS(s), dt.location) }
// AddMilli incrémente la milliseconde.
func (dt DateTime) AddMilli(v int) DateTime { return initDT(dt.addV(v), dt.location) }
// AddDuration incrémente une durée.
func (dt DateTime) AddDuration(dd Duration) DateTime { return initDT(dt.addDD(dd), dt.location) }
// BeginOfYear retourne la date en début dannée.
func (dt DateTime) BeginOfYear() DateTime { return initDT(dt.bY(), dt.location) }
// EndOfYear retourne la date en fin dannée.
func (dt DateTime) EndOfYear() DateTime { return initDT(dt.eY(), dt.location) }
// BeginOfMonth retourne la date en début de mois.
func (dt DateTime) BeginOfMonth() DateTime { return initDT(dt.bM(), dt.location) }
// EndOfMonth retourne la date en fin de mois.
func (dt DateTime) EndOfMonth() DateTime { return initDT(dt.eM(), dt.location) }
// BeginOfWeek retourne la date en début de semaine.
func (dt DateTime) BeginOfWeek() DateTime { return initDT(dt.bW(dt.location), dt.location) }
// EndOfWeek retourne la date en fin de semaine.
func (dt DateTime) EndOfWeek() DateTime { return initDT(dt.eW(dt.location), dt.location) }
// BeginOfDay retourne la date en début de jour.
func (dt DateTime) BeginOfDay() DateTime { return initDT(dt.bD(), dt.location) }
// EndOfDay retourne la date en fin de jour.
func (dt DateTime) EndOfDay() DateTime { return initDT(dt.eD(), dt.location) }
// BeginOfHour retourne la date en début dheure.
func (dt DateTime) BeginOfHour() DateTime { return initDT(dt.bH(), dt.location) }
// EndOfHour retourne la date en fin dheure.
func (dt DateTime) EndOfHour() DateTime { return initDT(dt.eH(), dt.location) }
// BeginOfMinute retourne la date en début de minute.
func (dt DateTime) BeginOfMinute() DateTime { return initDT(dt.bI(), dt.location) }
// EndOfMinute retourne la date en fin de minute.
func (dt DateTime) EndOfMinute() DateTime { return initDT(dt.eI(), dt.location) }
// BeginOfSecond retourne la date en début de seconde.
func (dt DateTime) BeginOfSecond() DateTime { return initDT(dt.bS(), dt.location) }
// EndOfSecond retourne la date en fin de seconde.
func (dt DateTime) EndOfSecond() DateTime { return initDT(dt.eS(), dt.location) }
// ToTime retourne la date dans le fuseau horaire indiqué.
func (dt DateTime) ToTime() time.Time { return dt.t(dt.location) }
// In retourne la date dans le fuseau horaire indiqué.
func (dt DateTime) In(l *time.Location) DateTime {
if dt.IsNil() {
return DateTimeNil()
}
return NewDateTimeFromTime(dt.ToTime().In(l), dt.p())
}
// ToTimezone retourne la date dans le fuseau horaire indiqué.
func (dt DateTime) ToTimezone(tz string) DateTime { return dt.In(timezone(tz)) }
// Location retourne le fuseau horaire.
func (dt DateTime) Location() *time.Location { return dt.location }
// IsDST retourne vrai si le fuseau horaire est à lheure dété.
func (dt DateTime) IsDST() bool { return dt.dst(dt.location) }
// Timestamp retourne le timestamp en secondes.
func (dt DateTime) TimeStamp() int64 { return dt.ts(dt.location) }
// TimestampMilli retourne le timestamp en millisecondes.
func (dt DateTime) TimeStampMilli() int64 { return dt.tv(dt.location) }
// Compare compare 2 dates.
func (dt1 DateTime) Compare(dt2 DateTime) int { return dt1.cmp(dt2.datetime) }
func (dt1 DateTime) Eq(dt2 DateTime) bool { return dt1.Compare(dt2) == 0 }
func (dt1 DateTime) Ne(dt2 DateTime) bool { return dt1.Compare(dt2) != 0 }
func (dt1 DateTime) Gt(dt2 DateTime) bool { return dt1.Compare(dt2) > 0 }
func (dt1 DateTime) Ge(dt2 DateTime) bool { return dt1.Compare(dt2) >= 0 }
func (dt1 DateTime) Lt(dt2 DateTime) bool { return dt1.Compare(dt2) < 0 }
func (dt1 DateTime) Le(dt2 DateTime) bool { return dt1.Compare(dt2) <= 0 }
func (dt DateTime) IsNow() bool { return dt.Eq(dt.Now()) }
func (dt DateTime) IsPast() bool { return dt.Lt(dt.Now()) }
func (dt DateTime) IsFuture() bool { return dt.Gt(dt.Now()) }
// DiffInMills retourne dt1-dt2 en millisecondes.
func (dt1 DateTime) DiffInMillis(dt2 DateTime) int {
return dt1.subV(dt2.datetime, dt1.location, dt2.location)
}
// DiffInSeconds retourne dt1 - dt2 en secondes.
func (dt1 DateTime) DiffInSeconds(dt2 DateTime) int {
return dt1.subS(dt2.datetime, dt1.location, dt2.location)
}
// DiffInMinutes retourne dt1 - dt2 en minutes.
func (dt1 DateTime) DiffInMinutes(dt2 DateTime) int {
return dt1.subI(dt2.datetime, dt1.location, dt2.location)
}
// DiffInHours retourne dt1 - dt2 en heures.
func (dt1 DateTime) DiffInHours(dt2 DateTime) int {
return dt1.subH(dt2.datetime, dt1.location, dt2.location)
}
// DiffInDays retourne dt1 - dt2 en jours.
func (dt1 DateTime) DiffInDays(dt2 DateTime) int {
return dt1.subD(dt2.datetime, dt1.location, dt2.location)
}
// DiffInWeeks retourne dt1 - dt2 en semaines.
func (dt1 DateTime) DiffInWeeks(dt2 DateTime) int {
return dt1.subW(dt2.datetime, dt1.location, dt2.location)
}
// DiffInMonths retourne dt1 - dt2 en mois.
func (dt1 DateTime) DiffInMonths(dt2 DateTime) int { return dt1.subM(dt2.datetime) }
// DiffInYears retourn dt1 - dt2 en années.
func (dt1 DateTime) DiffInYears(dt2 DateTime) int { return dt1.subY(dt2.datetime) }
// Format retourne une représentation de la date au format spécifié.
func (dt DateTime) Format(f string) string { return dt.f(f, dt.location) }
// String retourne une représentation de la date au format 'Y-m-d H:iT',
// 'Y-m-d H:i:sT' ou 'Y-m-d H:i:s.vT' suivant la précision.
func (dt DateTime) String() string { return dt.str(dt.location) }