Màj du README + commentaires datetime plus précis + ajout de la méthode String() à Range & Duration + Parsage d’une durée + gestion des périodes avec borne infinie à droite et/ou à gauche
This commit is contained in:
		
							parent
							
								
									41e37d8398
								
							
						
					
					
						commit
						976ac750b1
					
				
					 8 changed files with 277 additions and 123 deletions
				
			
		| 
						 | 
				
			
			@ -37,6 +37,15 @@ Le paquet **convert** fournit le nécessaire pour convertir des variables typée
 | 
			
		|||
 | 
			
		||||
Tous ces types sont convertibles entre eux.
 | 
			
		||||
 | 
			
		||||
### datetime
 | 
			
		||||
 | 
			
		||||
Le paquet **datetime** implémente des structures pour gérer des temps :
 | 
			
		||||
 | 
			
		||||
- datetime.Clock : pour gérer une heure dans la journée,
 | 
			
		||||
- datetime.Date : pour gérer une date, sans indication de l’heure,
 | 
			
		||||
- datetime.DateTime : pour gérer une date avec indication de l’heure.
 | 
			
		||||
- Range : pour gérer une période entre deux temps.
 | 
			
		||||
 | 
			
		||||
### format
 | 
			
		||||
 | 
			
		||||
Le paquet **format** fournit le nécessaire pour formater la sortie terminal :
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,14 @@ import (
 | 
			
		|||
type clock uint
 | 
			
		||||
 | 
			
		||||
// Precision représente la précision d’une horloge.
 | 
			
		||||
// Par exemple :
 | 
			
		||||
// - 15:06 est une horloge précise à la minute,
 | 
			
		||||
// - 15:06:02 est précise à la seconde,
 | 
			
		||||
// - 15:06:02.257 est précise à la milliseconde.
 | 
			
		||||
//
 | 
			
		||||
// La précision est utilisée dans Clock pour les comparaisons :
 | 
			
		||||
// les comparaisons entre deux horloges se font à la précision
 | 
			
		||||
// le l’horloge la moins précise.
 | 
			
		||||
type Precision uint
 | 
			
		||||
 | 
			
		||||
func newC0(h, i uint, e ...uint) clock {
 | 
			
		||||
| 
						 | 
				
			
			@ -213,11 +221,13 @@ func setClock(v uint, p Precision, l *time.Location) Clock {
 | 
			
		|||
	return newClock(newC(v, p), l)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewClock retourne une horloge dans le fuseau horaire par défaut.
 | 
			
		||||
// La précision est calculée automatiquement suivant que la seconde et la milliseconde sont indiquées.
 | 
			
		||||
// NewClock retourne une horloge à l’heure h et la minute i dans le fuseau horaire par défaut.
 | 
			
		||||
// La précision est calculée automatiquement suivant que la seconde et la milliseconde sont également
 | 
			
		||||
// présentes dans args.
 | 
			
		||||
func NewClock(h uint, i uint, args ...uint) Clock { return newClock(newC0(h, i, args...), DefaultTZ) }
 | 
			
		||||
 | 
			
		||||
// NewClockTZ agit comme NewClock mais dans le fuseau horaire tz.
 | 
			
		||||
// tz peut être mis sous la forme "Europe/Paris", "CET", "Local", etc.
 | 
			
		||||
func NewClockTZ(tz string, h uint, i uint, args ...uint) Clock {
 | 
			
		||||
	c := NewClock(h, i, args...)
 | 
			
		||||
	if c.valid() {
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +237,8 @@ func NewClockTZ(tz string, h uint, i uint, args ...uint) Clock {
 | 
			
		|||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewClockFromTime retourne l’heure à partir d’une date Go.
 | 
			
		||||
// NewClockFromTime retourne l’heure à partir d’une date Go t.
 | 
			
		||||
// Si la précision p n’est pas définie, c’est une précision à la ms.
 | 
			
		||||
func NewClockFromTime(t time.Time, p ...Precision) Clock {
 | 
			
		||||
	var (
 | 
			
		||||
		pp      = PrecisionMillisecond
 | 
			
		||||
| 
						 | 
				
			
			@ -243,15 +254,16 @@ func NewClockFromTime(t time.Time, p ...Precision) Clock {
 | 
			
		|||
	return setClock(ms(uint(h), uint(i), uint(s), uint(v)), pp, l)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClockNow retourne l’heure actuelle. Si tz est renseignée,
 | 
			
		||||
// ClockNow retourne l’heure actuelle avec une précision p. Si tz est renseignée,
 | 
			
		||||
// l’heure est placée dans le fuseau horaire indiqué.
 | 
			
		||||
func ClockNow(p Precision, tz ...string) Clock {
 | 
			
		||||
	return NewClockFromTime(now(tz...), p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Now retourne l’heure actuelle avec la même précision et le même fuseau horaire que c.
 | 
			
		||||
func (c Clock) Now() Clock { return ClockNow(c.p(), c.location.String()) }
 | 
			
		||||
 | 
			
		||||
// ClockGuess retourne l’heure à partir de e en essayant de deviner le format.
 | 
			
		||||
// ClockGuess retourne l’heure à partir de e et à la précision p en essayant de deviner le format.
 | 
			
		||||
func ClockGuess(p Precision, e string, tz ...string) Clock {
 | 
			
		||||
	if t, ok := guess(e, tz...).Get(); ok {
 | 
			
		||||
		return NewClockFromTime(t, p)
 | 
			
		||||
| 
						 | 
				
			
			@ -260,7 +272,7 @@ func ClockGuess(p Precision, e string, tz ...string) Clock {
 | 
			
		|||
	return ClockNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ClockParse retourne l’heure à partir de e en spécifiant le format f.
 | 
			
		||||
// ClockParse retourne l’heure à partir de e et à la précision p en spécifiant le format f.
 | 
			
		||||
func ClockParse(p Precision, e, f string, tz ...string) Clock {
 | 
			
		||||
	if t, ok := parse(e, f).Get(); ok {
 | 
			
		||||
		return NewClockFromTime(t, p)
 | 
			
		||||
| 
						 | 
				
			
			@ -299,19 +311,19 @@ func (c Clock) Hour() uint { return c.h() }
 | 
			
		|||
// Clock retourne l’heure, la minute, la seconde et la milliseconde.
 | 
			
		||||
func (c Clock) Clock() (h, i, s, v uint) { return c.h(), c.i(), c.s(), c.v() }
 | 
			
		||||
 | 
			
		||||
// SetMilli modifie la milliseconde.
 | 
			
		||||
// SetMilli modifie la milliseconde de la seconde.
 | 
			
		||||
func (c Clock) SetMilli(v uint) Clock { return newClock(c.setV(v), c.location) }
 | 
			
		||||
 | 
			
		||||
// SetSecond modifie la seconde.
 | 
			
		||||
// SetSecond modifie la seconde de la minute, et la milliseconde, si v est renseignée.
 | 
			
		||||
func (c Clock) SetSecond(s uint, v ...uint) Clock { return newClock(c.setS(s, v...), c.location) }
 | 
			
		||||
 | 
			
		||||
// SetMinute modifie la minute.
 | 
			
		||||
// SetMinute modifie la minute de l’heure, ainsi que la seconde et la millisecondes si elles sont renseignées.
 | 
			
		||||
func (c Clock) SetMinute(i uint, args ...uint) Clock { return newClock(c.setI(i, args...), c.location) }
 | 
			
		||||
 | 
			
		||||
// SetHour modifie l’heure.
 | 
			
		||||
// SetHour modifie l’heure et, facultativement, la minute, la seconde et la milliseconde.
 | 
			
		||||
func (c Clock) SetHour(h uint, args ...uint) Clock { return newClock(c.setH(h, args...), c.location) }
 | 
			
		||||
 | 
			
		||||
// SetPrecision modifie la précision.
 | 
			
		||||
// SetPrecision retourne l’horloge avec la précision p.
 | 
			
		||||
func (c Clock) SetPrecision(p Precision) Clock { return newClock(c.setP(p), c.location) }
 | 
			
		||||
 | 
			
		||||
// Add ajoute un nombre d’heures et de minutes, et, facultativement,
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +339,7 @@ func (c Clock) AddMinute(i int) Clock { return newClock(c.addI(i), c.location) }
 | 
			
		|||
// AddSecond ajoute une durée en secondes.
 | 
			
		||||
func (c Clock) AddSecond(s int) Clock { return newClock(c.addS(s), c.location) }
 | 
			
		||||
 | 
			
		||||
// AddMilli ajoute une durée en ms.
 | 
			
		||||
// AddMilli ajoute une durée en millisecondes.
 | 
			
		||||
func (c Clock) AddMilli(v int) Clock { return newClock(c.addV(v), c.location) }
 | 
			
		||||
 | 
			
		||||
// AddDuration ajoute une durée.
 | 
			
		||||
| 
						 | 
				
			
			@ -369,11 +381,12 @@ func (c Clock) In(l *time.Location) Clock {
 | 
			
		|||
	return NewClockFromTime(c.ToTime().In(l))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToTimezone retourne l’heure dans le fuseau horaire indiqué.
 | 
			
		||||
func (c Clock) ToTimezone(tz string) Clock { return c.In(timezone(tz)) }
 | 
			
		||||
// InTZ agit comme In mais en fournissant le fuseau horaire sous forme
 | 
			
		||||
// de chaîne de caractères.
 | 
			
		||||
func (c Clock) inTZ(tz string) Clock { return c.In(timezone(tz)) }
 | 
			
		||||
 | 
			
		||||
// Location retourne le fuseau horaire.
 | 
			
		||||
func (c Clock) Location() *time.Location { return c.location }
 | 
			
		||||
// TZ retourne le fuseau horaire.
 | 
			
		||||
func (c Clock) TZ() *time.Location { return c.location }
 | 
			
		||||
 | 
			
		||||
// IsDST retourne vrai si le fuseau horaire est à l’heure d’été.
 | 
			
		||||
func (c Clock) IsDST() bool { return c.dst(c.location) }
 | 
			
		||||
| 
						 | 
				
			
			@ -398,14 +411,26 @@ func (c1 Clock) Ge(c2 Clock) bool { return c1.Compare(c2) >= 0 }
 | 
			
		|||
func (c1 Clock) Lt(c2 Clock) bool { return c1.Compare(c2) < 0 }
 | 
			
		||||
func (c1 Clock) Le(c2 Clock) bool { return c1.Compare(c2) <= 0 }
 | 
			
		||||
 | 
			
		||||
func (c Clock) IsNow() bool    { return c.Eq(c.Now()) }
 | 
			
		||||
func (c Clock) IsPast() bool   { return c.Lt(c.Now()) }
 | 
			
		||||
// IsNow retourne vrai si l’horloge est à l’heure actuelle.
 | 
			
		||||
func (c Clock) IsNow() bool { return c.Eq(c.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsPast retourne vrai si l’horloge est située dans le passé.
 | 
			
		||||
func (c Clock) IsPast() bool { return c.Lt(c.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsFuture retourne vrai si l’horloge est située dans le futur.
 | 
			
		||||
func (c Clock) IsFuture() bool { return c.Gt(c.Now()) }
 | 
			
		||||
 | 
			
		||||
func (c1 Clock) DiffInMillis(c2 Clock) int  { return c1.subV(c2.clock) }
 | 
			
		||||
// DiffInMillis retourne c1 - c2 en millisecondes.
 | 
			
		||||
func (c1 Clock) DiffInMillis(c2 Clock) int { return c1.subV(c2.clock) }
 | 
			
		||||
 | 
			
		||||
// DiffInSeconds retourne c1 - c2 en secondes.
 | 
			
		||||
func (c1 Clock) DiffInSeconds(c2 Clock) int { return c1.subS(c2.clock) }
 | 
			
		||||
 | 
			
		||||
// DiffInMinutes retourne c1 - c2 en minutes.
 | 
			
		||||
func (c1 Clock) DiffInMinutes(c2 Clock) int { return c1.subI(c2.clock) }
 | 
			
		||||
func (c1 Clock) DiffInHours(c2 Clock) int   { return c1.subH(c2.clock) }
 | 
			
		||||
 | 
			
		||||
// DiffInHours retourne c1 - c2 en heures.
 | 
			
		||||
func (c1 Clock) DiffInHours(c2 Clock) int { return c1.subH(c2.clock) }
 | 
			
		||||
 | 
			
		||||
// Format retourne une représentation de l’heure au format spécifié.
 | 
			
		||||
func (c Clock) Format(format string) string { return c.f(format, c.location) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,17 +103,17 @@ const (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// représentation de l’unité sous forme de caractère
 | 
			
		||||
	unitToByte = map[Unit]byte{
 | 
			
		||||
		NoUnit:      0,
 | 
			
		||||
		Millisecond: 'N',
 | 
			
		||||
		Second:      'S',
 | 
			
		||||
		Minute:      'M',
 | 
			
		||||
		Hour:        'H',
 | 
			
		||||
		Day:         'd',
 | 
			
		||||
		Week:        'w',
 | 
			
		||||
		Month:       'm',
 | 
			
		||||
		Year:        'y',
 | 
			
		||||
	// Représentation de l’unité sous forme de caractères
 | 
			
		||||
	unitToString = map[Unit]string{
 | 
			
		||||
		NoUnit:      "",
 | 
			
		||||
		Millisecond: "ms",
 | 
			
		||||
		Second:      "s",
 | 
			
		||||
		Minute:      "m",
 | 
			
		||||
		Hour:        "h",
 | 
			
		||||
		Day:         "J",
 | 
			
		||||
		Week:        "S",
 | 
			
		||||
		Month:       "M",
 | 
			
		||||
		Year:        "A",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	maskDate = map[string]date{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,12 +205,14 @@ func newDate(t date, l *time.Location) Date {
 | 
			
		|||
	return DateNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDate retourne la date dans le fuseau horaire demandé.
 | 
			
		||||
// NewDate retourne la date à partir de l’année, du mois et du jour.
 | 
			
		||||
// Si le fuseau horaire tz est renseigné, c’est le fuseau utilisé,
 | 
			
		||||
// sinon, c’est le fuseau par défaut.
 | 
			
		||||
func NewDate(y int, m, d uint, tz ...string) Date {
 | 
			
		||||
	return newDate(newD(y, m, d), timezone(tz...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDateFromTime retourne la date à partir d’une date Go.
 | 
			
		||||
// NewDateFromTime retourne la date à partir d’une date Go t.
 | 
			
		||||
func NewDateFromTime(t time.Time) Date {
 | 
			
		||||
	y, m, d := t.Date()
 | 
			
		||||
	l := t.Location()
 | 
			
		||||
| 
						 | 
				
			
			@ -222,6 +224,7 @@ func NewDateFromTime(t time.Time) Date {
 | 
			
		|||
// la date est placée dans le fuseau horaire indiqué.
 | 
			
		||||
func DateNow(tz ...string) Date { return NewDateFromTime(now(tz...)) }
 | 
			
		||||
 | 
			
		||||
// Now retourne la date actuelle dans le même fuseau horaire que t.
 | 
			
		||||
func (t Date) Now() Date { return DateNow(t.location.String()) }
 | 
			
		||||
 | 
			
		||||
// DateGuess retourne la date à partir de e en essayant de deviner le format.
 | 
			
		||||
| 
						 | 
				
			
			@ -233,7 +236,7 @@ func DateGuess(e string, tz ...string) Date {
 | 
			
		|||
	return DateNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DateParse retourne la date à partir de v en spécifiant le format f.
 | 
			
		||||
// DateParse retourne la date à partir de e en spécifiant le format f.
 | 
			
		||||
func DateParse(e, f string, tz ...string) Date {
 | 
			
		||||
	if t, ok := parse(e, f).Get(); ok {
 | 
			
		||||
		return NewDateFromTime(t)
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +266,7 @@ func (t Date) YearDay() uint { return t.yd() }
 | 
			
		|||
// WeekDay retourne le jour de la semaine (de 0 à 6 en commençant par dimanche).
 | 
			
		||||
func (t Date) WeekDay() uint { return t.wd(t.location) }
 | 
			
		||||
 | 
			
		||||
// IsBissextil retourn vrai si la date est dans une année bissextile.
 | 
			
		||||
// IsBissextil retourne vrai si la date est dans une année bissextile.
 | 
			
		||||
func (t Date) IsBissextil() bool { return t.b() }
 | 
			
		||||
 | 
			
		||||
// DaysInYear retourne le nombre de jours dans l’année.
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +293,7 @@ func (t Date) AddYear(y int) Date { return newDate(t.addY(y), t.location) }
 | 
			
		|||
// AddMonth incrémente le mois.
 | 
			
		||||
func (t Date) AddMonth(m int) Date { return newDate(t.addM(m), t.location) }
 | 
			
		||||
 | 
			
		||||
// AddWeek incrémente la date de week semaines.
 | 
			
		||||
// AddWeek incrémente la date de w semaines.
 | 
			
		||||
func (t Date) AddWeek(w int) Date { return newDate(t.addW(w), t.location) }
 | 
			
		||||
 | 
			
		||||
// AddDay incrémente le jour.
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +317,7 @@ func (t Date) EndOfMonth() Date { return newDate(t.eM(), t.location) }
 | 
			
		|||
// BeginOfWeek retourne la date du premier jour de la semaine (ie. lundi).
 | 
			
		||||
func (t Date) BeginOfWeek() Date { return newDate(t.bW(t.location), t.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfWeek retourne la date du dernier jour de la semaine.
 | 
			
		||||
// EndOfWeek retourne la date du dernier jour de la semaine (e. dimanche).
 | 
			
		||||
func (t Date) EndOfWeek() Date { return newDate(t.eW(t.location), t.location) }
 | 
			
		||||
 | 
			
		||||
// ToTime convertit la date en date de type time.Time.
 | 
			
		||||
| 
						 | 
				
			
			@ -329,11 +332,12 @@ func (t Date) In(l *time.Location) Date {
 | 
			
		|||
	return NewDateFromTime(t.t(t.location).In(l))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToTimezone retourne la date dans le fuseau horaire indiqué.
 | 
			
		||||
// InTZ agit comme In mais en fournissant le fuseau horaire sous forme
 | 
			
		||||
// de chaîne de caractères.
 | 
			
		||||
func (t Date) ToTimezone(tz string) Date { return t.In(timezone(tz)) }
 | 
			
		||||
 | 
			
		||||
// Location retourne le fuseau horaire.
 | 
			
		||||
func (t Date) Location() *time.Location { return t.location }
 | 
			
		||||
// TZ retourne le fuseau horaire.
 | 
			
		||||
func (t Date) TZ() *time.Location { return t.location }
 | 
			
		||||
 | 
			
		||||
// IsDST retourne vrai si le fuseau horaire est à l’heure d’été.
 | 
			
		||||
func (t Date) IsDST() bool { return t.dst(t.location) }
 | 
			
		||||
| 
						 | 
				
			
			@ -341,10 +345,11 @@ func (t Date) IsDST() bool { return t.dst(t.location) }
 | 
			
		|||
// Timestamp retourne le timestamp en secondes.
 | 
			
		||||
func (t Date) Timestamp() int64 { return t.ts(t.location) }
 | 
			
		||||
 | 
			
		||||
// TimestampMilli retourne le timestamp en secondes.
 | 
			
		||||
// TimestampMilli retourne le timestamp en millisecondes.
 | 
			
		||||
func (t Date) TimestampMilli() int64 { return t.tv(t.location) }
 | 
			
		||||
 | 
			
		||||
// Compare compare 2 dates.
 | 
			
		||||
// La comparaison s’effectue après normalisation, ie. dans le même fuseau horaire.
 | 
			
		||||
func (t1 Date) Compare(t2 Date) int { return t1.cmp(t2.In(t1.location).date) }
 | 
			
		||||
 | 
			
		||||
func (t1 Date) Eq(t2 Date) bool { return t1.Compare(t2) == 0 }
 | 
			
		||||
| 
						 | 
				
			
			@ -354,21 +359,33 @@ func (t1 Date) Ge(t2 Date) bool { return t1.Compare(t2) >= 0 }
 | 
			
		|||
func (t1 Date) Lt(t2 Date) bool { return t1.Compare(t2) < 0 }
 | 
			
		||||
func (t1 Date) Le(t2 Date) bool { return t1.Compare(t2) <= 0 }
 | 
			
		||||
 | 
			
		||||
func (t Date) IsNow() bool    { return t.Eq(t.Now()) }
 | 
			
		||||
func (t Date) IsPast() bool   { return t.Lt(t.Now()) }
 | 
			
		||||
// IsNow retourne vrai si la date est située aujourd’hui.
 | 
			
		||||
func (t Date) IsNow() bool { return t.Eq(t.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsPast retourne vrai si la date est situé dans le passé.
 | 
			
		||||
func (t Date) IsPast() bool { return t.Lt(t.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsFuture retourne vrai si la date est situé dans le futur.
 | 
			
		||||
func (t Date) IsFuture() bool { return t.Gt(t.Now()) }
 | 
			
		||||
 | 
			
		||||
func (t1 Date) diff(t2 Date) (dy, dm, dd int) {
 | 
			
		||||
	return t1.y() - t2.y(), int(t1.m()) - int(t2.m()), int(t1.d()) - int(t2.d())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t1 Date) DiffInDays(t2 Date) int   { return t1.subD(t2.date, t1.location, t2.location) }
 | 
			
		||||
func (t1 Date) DiffInWeeks(t2 Date) int  { return t1.subW(t2.date, t1.location, t2.location) }
 | 
			
		||||
// DiffInDays retourne t1 - t2 en jours.
 | 
			
		||||
func (t1 Date) DiffInDays(t2 Date) int { return t1.subD(t2.date, t1.location, t2.location) }
 | 
			
		||||
 | 
			
		||||
// DiffInWeeks retourne t1 - t2 en semaines.
 | 
			
		||||
func (t1 Date) DiffInWeeks(t2 Date) int { return t1.subW(t2.date, t1.location, t2.location) }
 | 
			
		||||
 | 
			
		||||
// DiffInMonths retourne t1 - t2 en mois.
 | 
			
		||||
func (t1 Date) DiffInMonths(t2 Date) int { return t1.subM(t2.date) }
 | 
			
		||||
func (t1 Date) DiffInYears(t2 Date) int  { return t1.subY(t2.date) }
 | 
			
		||||
 | 
			
		||||
// DiffInYears retourne t1 - t2 en années.
 | 
			
		||||
func (t1 Date) DiffInYears(t2 Date) int { return t1.subY(t2.date) }
 | 
			
		||||
 | 
			
		||||
// Format retourne une représentation de la date au format spécifié.
 | 
			
		||||
func (t Date) Format(format string) string { return t.f(format, t.location) }
 | 
			
		||||
func (t Date) Format(f string) string { return t.f(f, t.location) }
 | 
			
		||||
 | 
			
		||||
// String retourne la date au format Y-m-d.
 | 
			
		||||
func (t Date) String() string { return t.str(t.location) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -176,7 +176,7 @@ func (dt datetime) f(f string, l *time.Location) string {
 | 
			
		|||
}
 | 
			
		||||
func (dt datetime) str(l *time.Location) string { return dt.f("Y-m-d", l) }
 | 
			
		||||
 | 
			
		||||
// DateTime représente une indication de temps.
 | 
			
		||||
// DateTime représente une indication de temps (date + heure).
 | 
			
		||||
type DateTime struct {
 | 
			
		||||
	datetime
 | 
			
		||||
	location *time.Location
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +193,10 @@ func initDT(dt datetime, l *time.Location) DateTime {
 | 
			
		|||
	return DateTime{dt, l}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDateTime retourne un temps dans le fuseau horaire par défaut.
 | 
			
		||||
// NewDateTime retourne un temps dans le fuseau horaire par défaut avec :
 | 
			
		||||
// - y, m, d : année, mois, jour
 | 
			
		||||
// - h, i : heure, minute,
 | 
			
		||||
// - args : seconde, puis milliseconde.
 | 
			
		||||
// 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +212,9 @@ func NewDateTimeTZ(tz string, y int, m, d, h, i uint, args ...uint) DateTime {
 | 
			
		|||
	return dt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDateTimeFromTime retourne le temps à partir d’une date Go.
 | 
			
		||||
// NewDateTimeFromTime retourne le temps à partir d’une date Go t.
 | 
			
		||||
// Si la précision p est fournie, c’est la précision utilisée,
 | 
			
		||||
// sinon, c’est la précision à la milliseconde.
 | 
			
		||||
func NewDateTimeFromTime(t time.Time, p ...Precision) DateTime {
 | 
			
		||||
	var (
 | 
			
		||||
		pp      = PrecisionMillisecond
 | 
			
		||||
| 
						 | 
				
			
			@ -226,15 +231,16 @@ func NewDateTimeFromTime(t time.Time, p ...Precision) DateTime {
 | 
			
		|||
	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,
 | 
			
		||||
// DateTimeNow retourne le temps à la précision p. 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Now retourne le temps actuel avec la précision et le fuseau horaire de dt.
 | 
			
		||||
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.
 | 
			
		||||
// DateTimeGuess retourne le temps à 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +249,7 @@ func DateTimeGuess(p Precision, e string, tz ...string) DateTime {
 | 
			
		|||
	return DateTimeNil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DateTimeParse retourne la date à partir de e en spécifiant le format f.
 | 
			
		||||
// DateTimeParse retourne le temps à 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +261,7 @@ func DateTimeParse(p Precision, e, f string, tz ...string) DateTime {
 | 
			
		|||
// Precision retourne la précision de l’heure.
 | 
			
		||||
func (dt DateTime) Precision() Precision { return dt.p() }
 | 
			
		||||
 | 
			
		||||
// IsNil retourne vrai si la date est nulle.
 | 
			
		||||
// IsNil retourne vrai si le temps est nul.
 | 
			
		||||
func (dt DateTime) IsNil() bool { return !dt.valid() }
 | 
			
		||||
 | 
			
		||||
// Year retourne l’année.
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +270,7 @@ func (dt DateTime) Year() int { return dt.y() }
 | 
			
		|||
// Month retourne le mois.
 | 
			
		||||
func (dt DateTime) Month() uint { return dt.m() }
 | 
			
		||||
 | 
			
		||||
// Day retourne le .
 | 
			
		||||
// Day retourne le jour.
 | 
			
		||||
func (dt DateTime) Day() uint { return dt.d() }
 | 
			
		||||
 | 
			
		||||
// Hour retourne l’heure.
 | 
			
		||||
| 
						 | 
				
			
			@ -318,32 +324,32 @@ 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 l’année.
 | 
			
		||||
// SetYear modifie l’année, et facultativement, le mois, le jour, etc.
 | 
			
		||||
func (dt DateTime) SetYear(y int, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setY(y, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetMonth modifie le mois.
 | 
			
		||||
// SetMonth modifie le mois et facultativement le jour, l’heure, etc.
 | 
			
		||||
func (dt DateTime) SetMonth(m uint, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setM(m, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetDay modifie le jour.
 | 
			
		||||
// SetDay modifie le jour et facultativement l’heure, la minute, etc..
 | 
			
		||||
func (dt DateTime) SetDay(d uint, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setD(d, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetHour modifie l’heure.
 | 
			
		||||
// SetHour modifie l’heure et facultativement la minute, la seconde, etc.
 | 
			
		||||
func (dt DateTime) SetHour(h uint, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setH(h, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetMinute modifie la minute.
 | 
			
		||||
// SetMinute modifie la minute et facultativement la seconde et la milliseconde.
 | 
			
		||||
func (dt DateTime) SetMinute(i uint, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setI(i, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetSecond modifie la seconde.
 | 
			
		||||
// SetSecond modifie la seconde et facultativement la milliseconde.
 | 
			
		||||
func (dt DateTime) SetSecond(s uint, args ...uint) DateTime {
 | 
			
		||||
	return initDT(dt.setS(s, args...), dt.location)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -395,52 +401,52 @@ func (dt DateTime) AddMilli(v int) DateTime { return initDT(dt.addV(v), dt.locat
 | 
			
		|||
// 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 d’année.
 | 
			
		||||
// BeginOfYear retourne le temps en début d’année au début du jour.
 | 
			
		||||
func (dt DateTime) BeginOfYear() DateTime { return initDT(dt.bY(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfYear retourne la date en fin d’année.
 | 
			
		||||
// EndOfYear retourne le temps en fin d’année à la fin du jour.
 | 
			
		||||
func (dt DateTime) EndOfYear() DateTime { return initDT(dt.eY(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfMonth retourne la date en début de mois.
 | 
			
		||||
// BeginOfMonth retourne le temps en début de mois au début du jour.
 | 
			
		||||
func (dt DateTime) BeginOfMonth() DateTime { return initDT(dt.bM(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfMonth retourne la date en fin de mois.
 | 
			
		||||
// EndOfMonth retourne le temps en fin de mois à la fin du jour.
 | 
			
		||||
func (dt DateTime) EndOfMonth() DateTime { return initDT(dt.eM(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfWeek retourne la date en début de semaine.
 | 
			
		||||
// BeginOfWeek retourne le temps en début de semaine au début du jour.
 | 
			
		||||
func (dt DateTime) BeginOfWeek() DateTime { return initDT(dt.bW(dt.location), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfWeek retourne la date en fin de semaine.
 | 
			
		||||
// EndOfWeek retourne le temps en fin de semaine à la fin du jour.
 | 
			
		||||
func (dt DateTime) EndOfWeek() DateTime { return initDT(dt.eW(dt.location), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfDay retourne la date en début de jour.
 | 
			
		||||
// BeginOfDay retourne le temps en début de jour.
 | 
			
		||||
func (dt DateTime) BeginOfDay() DateTime { return initDT(dt.bD(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfDay retourne la date en fin de jour.
 | 
			
		||||
// EndOfDay retourne le temps en fin de jour.
 | 
			
		||||
func (dt DateTime) EndOfDay() DateTime { return initDT(dt.eD(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfHour retourne la date en début d’heure.
 | 
			
		||||
// BeginOfHour retourne le temps en début d’heure.
 | 
			
		||||
func (dt DateTime) BeginOfHour() DateTime { return initDT(dt.bH(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfHour retourne la date en fin d’heure.
 | 
			
		||||
// EndOfHour retourne le temps en fin d’heure.
 | 
			
		||||
func (dt DateTime) EndOfHour() DateTime { return initDT(dt.eH(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfMinute retourne la date en début de minute.
 | 
			
		||||
// BeginOfMinute retourne le temps en début de minute.
 | 
			
		||||
func (dt DateTime) BeginOfMinute() DateTime { return initDT(dt.bI(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfMinute retourne la date en fin de minute.
 | 
			
		||||
// EndOfMinute retourne le temps en fin de minute.
 | 
			
		||||
func (dt DateTime) EndOfMinute() DateTime { return initDT(dt.eI(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// BeginOfSecond retourne la date en début de seconde.
 | 
			
		||||
// BeginOfSecond retourne le temps en début de seconde.
 | 
			
		||||
func (dt DateTime) BeginOfSecond() DateTime { return initDT(dt.bS(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// EndOfSecond retourne la date en fin de seconde.
 | 
			
		||||
// EndOfSecond retourne le temps en fin de seconde.
 | 
			
		||||
func (dt DateTime) EndOfSecond() DateTime { return initDT(dt.eS(), dt.location) }
 | 
			
		||||
 | 
			
		||||
// ToTime retourne la date dans le fuseau horaire indiqué.
 | 
			
		||||
// ToTime retourne le temps 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é.
 | 
			
		||||
// In retourne le temps dans le fuseau horaire indiqué.
 | 
			
		||||
func (dt DateTime) In(l *time.Location) DateTime {
 | 
			
		||||
	if dt.IsNil() {
 | 
			
		||||
		return DateTimeNil()
 | 
			
		||||
| 
						 | 
				
			
			@ -449,11 +455,12 @@ func (dt DateTime) In(l *time.Location) DateTime {
 | 
			
		|||
	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)) }
 | 
			
		||||
// InTZ agit comme In mais en fournissant le fuseau horaire sous forme
 | 
			
		||||
// de chaîne de caractères.
 | 
			
		||||
func (dt DateTime) InTZ(tz string) DateTime { return dt.In(timezone(tz)) }
 | 
			
		||||
 | 
			
		||||
// Location retourne le fuseau horaire.
 | 
			
		||||
func (dt DateTime) Location() *time.Location { return dt.location }
 | 
			
		||||
// TZ retourne le fuseau horaire.
 | 
			
		||||
func (dt DateTime) TZ() *time.Location { return dt.location }
 | 
			
		||||
 | 
			
		||||
// IsDST retourne vrai si le fuseau horaire est à l’heure d’été.
 | 
			
		||||
func (dt DateTime) IsDST() bool { return dt.dst(dt.location) }
 | 
			
		||||
| 
						 | 
				
			
			@ -464,7 +471,7 @@ 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.
 | 
			
		||||
// Compare compare 2 temps après normalisation du fuseau horaire et de la précision.
 | 
			
		||||
func (dt1 DateTime) Compare(dt2 DateTime) int { return dt1.cmp(dt2.datetime) }
 | 
			
		||||
 | 
			
		||||
func (dt1 DateTime) Eq(dt2 DateTime) bool { return dt1.Compare(dt2) == 0 }
 | 
			
		||||
| 
						 | 
				
			
			@ -474,11 +481,16 @@ 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()) }
 | 
			
		||||
// IsNow retourne vrai si le temps est le temps actuel.
 | 
			
		||||
func (dt DateTime) IsNow() bool { return dt.Eq(dt.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsPast retourne vrai si le temps est situé dans le passé.
 | 
			
		||||
func (dt DateTime) IsPast() bool { return dt.Lt(dt.Now()) }
 | 
			
		||||
 | 
			
		||||
// IsPast retourne vrai si le temps est situé dans le futur.
 | 
			
		||||
func (dt DateTime) IsFuture() bool { return dt.Gt(dt.Now()) }
 | 
			
		||||
 | 
			
		||||
// DiffInMills retourne dt1-dt2 en millisecondes.
 | 
			
		||||
// DiffInMills retourne dt1 - dt2 en millisecondes.
 | 
			
		||||
func (dt1 DateTime) DiffInMillis(dt2 DateTime) int {
 | 
			
		||||
	return dt1.subV(dt2.datetime, dt1.location, dt2.location)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -514,9 +526,9 @@ func (dt1 DateTime) DiffInMonths(dt2 DateTime) int { return dt1.subM(dt2.datetim
 | 
			
		|||
// 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é.
 | 
			
		||||
// Format retourne une représentation du temps 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',
 | 
			
		||||
// String retourne une représentation du temps 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) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,11 +2,15 @@ package datetime
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Unit est une unité de durée.
 | 
			
		||||
type Unit uint
 | 
			
		||||
 | 
			
		||||
func (u Unit) String() string { return unitToString[u] }
 | 
			
		||||
 | 
			
		||||
// Duration est une durée entre deux repères de temps.
 | 
			
		||||
type Duration int
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +23,26 @@ func NewDuration(value int, unit Unit) Duration {
 | 
			
		|||
	return (Duration(value) << bitsUnit) | Duration(unit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDuration retourne une durée à partir d’une chaîne de caractères.
 | 
			
		||||
func ParseDuration(e string) Duration {
 | 
			
		||||
	r := regexp.MustCompile(`^(\d+)(\w+)$`)
 | 
			
		||||
	if !r.MatchString(e) {
 | 
			
		||||
		return DurationNil
 | 
			
		||||
	}
 | 
			
		||||
	spl := r.FindAllStringSubmatch(e, 1)[0]
 | 
			
		||||
 | 
			
		||||
	v, _ := strconv.Atoi(spl[1])
 | 
			
		||||
	u := NoUnit
 | 
			
		||||
	for uu, su := range unitToString {
 | 
			
		||||
		if su == spl[2] {
 | 
			
		||||
			u = uu
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewDuration(v, u)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Value retourne la valeur de la durée, sans l’unité.
 | 
			
		||||
func (d Duration) Value() int { return int(d >> bitsUnit) }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,5 +75,5 @@ func (d Duration) String() string {
 | 
			
		|||
 | 
			
		||||
	v, u := d.Value(), d.Unit()
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%d%c", v, unitToByte[u])
 | 
			
		||||
	return fmt.Sprintf("%d%s", v, u)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ func format_B(t time.Time) string {
 | 
			
		|||
	h, m, s := t.Clock()
 | 
			
		||||
	n := t.Nanosecond() / NanosecondPerMillisecond
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%03d", sit(uint(h), uint(m), uint(s), uint(n)))
 | 
			
		||||
	return fmt.Sprintf("%03d", uint(sit(uint(h), uint(m), uint(s), uint(n))))
 | 
			
		||||
}
 | 
			
		||||
func format_g(t time.Time) string {
 | 
			
		||||
	h := t.Hour() % 12
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
package datetime
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	. "gitea.zaclys.com/bvaudour/gob/option"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +18,8 @@ type TimeComparator[E any] interface {
 | 
			
		|||
	IsPast() bool
 | 
			
		||||
	IsFuture() bool
 | 
			
		||||
	Now() E
 | 
			
		||||
	String() string
 | 
			
		||||
	IsNil() bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Min retourne le temps le plus petit.
 | 
			
		||||
| 
						 | 
				
			
			@ -40,21 +44,74 @@ func Max[C TimeComparator[C]](e C, args ...C) C {
 | 
			
		|||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Range représente une période entre deux bornes temporelles.
 | 
			
		||||
func minB[C TimeComparator[C]](e1, e2 C) C {
 | 
			
		||||
	if e1.IsNil() {
 | 
			
		||||
		return e1
 | 
			
		||||
	} else if e2.IsNil() {
 | 
			
		||||
		return e2
 | 
			
		||||
	}
 | 
			
		||||
	return Min(e1, e2)
 | 
			
		||||
}
 | 
			
		||||
func maxB[C TimeComparator[C]](e1, e2 C) C {
 | 
			
		||||
	if e1.IsNil() {
 | 
			
		||||
		return e2
 | 
			
		||||
	} else if e2.IsNil() {
 | 
			
		||||
		return e1
 | 
			
		||||
	}
 | 
			
		||||
	return Max(e1, e2)
 | 
			
		||||
}
 | 
			
		||||
func minE[C TimeComparator[C]](e1, e2 C) C {
 | 
			
		||||
	if e1.IsNil() {
 | 
			
		||||
		return e2
 | 
			
		||||
	} else if e2.IsNil() {
 | 
			
		||||
		return e1
 | 
			
		||||
	}
 | 
			
		||||
	return Min(e1, e2)
 | 
			
		||||
}
 | 
			
		||||
func maxE[C TimeComparator[C]](e1, e2 C) C {
 | 
			
		||||
	if e1.IsNil() {
 | 
			
		||||
		return e1
 | 
			
		||||
	} else if e2.IsNil() {
 | 
			
		||||
		return e2
 | 
			
		||||
	}
 | 
			
		||||
	return Max(e1, e2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Range représente une période entre deux bornes temporelles begin et end.
 | 
			
		||||
// Si begin est nul, cela représente ]-∞ ; end].
 | 
			
		||||
// Se end est nul, cela représent [begin; +∞[.
 | 
			
		||||
type Range[C TimeComparator[C]] struct {
 | 
			
		||||
	begin, end C
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRange retourne une période entre begin et end.
 | 
			
		||||
// Si begin < end, les bornes sont inversées.
 | 
			
		||||
// Si begin < end, le programme panique.
 | 
			
		||||
func NewRange[C TimeComparator[C]](begin, end C) Range[C] {
 | 
			
		||||
	if begin.Gt(end) {
 | 
			
		||||
		begin, end = end, begin
 | 
			
		||||
	if !begin.IsNil() && !end.IsNil() && begin.Gt(end) {
 | 
			
		||||
		panic("begin should be located in past of end.")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Range[C]{begin, end}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func gt[C TimeComparator[C]](e C, strict ...bool) func(C) bool {
 | 
			
		||||
	if len(strict) == 0 || !strict[0] {
 | 
			
		||||
		return e.Ge
 | 
			
		||||
	}
 | 
			
		||||
	return e.Ge
 | 
			
		||||
}
 | 
			
		||||
func lt[C TimeComparator[C]](e C, strict ...bool) func(C) bool {
 | 
			
		||||
	if len(strict) == 0 || !strict[0] {
 | 
			
		||||
		return e.Le
 | 
			
		||||
	}
 | 
			
		||||
	return e.Le
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r Range[C]) bE(e C, strict ...bool) bool { return r.end.IsNil() || lt(e, strict...)(r.end) }
 | 
			
		||||
func (r Range[C]) aE(e C, strict ...bool) bool { return !r.end.IsNil() && gt(e, strict...)(r.end) }
 | 
			
		||||
func (r Range[C]) bB(e C, strict ...bool) bool { return !r.begin.IsNil() || lt(e, strict...)(r.begin) }
 | 
			
		||||
func (r Range[C]) aB(e C, strict ...bool) bool { return r.begin.IsNil() || gt(e, strict...)(r.begin) }
 | 
			
		||||
 | 
			
		||||
// Begin retourne le début de la période.
 | 
			
		||||
func (r Range[C]) Begin() C { return r.begin }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,22 +119,22 @@ func (r Range[C]) Begin() C { return r.begin }
 | 
			
		|||
func (r Range[C]) End() C { return r.end }
 | 
			
		||||
 | 
			
		||||
// Before retourne vrai si e est située avant la période.
 | 
			
		||||
func (r Range[C]) Before(e C) bool { return e.Lt(r.begin) }
 | 
			
		||||
func (r Range[C]) Before(e C) bool { return r.bB(e, true) }
 | 
			
		||||
 | 
			
		||||
// After retourne vrai si e est située après la période.
 | 
			
		||||
func (r Range[C]) After(e C) bool { return e.Gt(r.end) }
 | 
			
		||||
func (r Range[C]) After(e C) bool { return r.aE(e, true) }
 | 
			
		||||
 | 
			
		||||
// Contains retourne vrai si e ∈ [begin;end].
 | 
			
		||||
func (r Range[C]) Contains(e C) bool { return e.Ge(r.begin) && e.Le(r.end) }
 | 
			
		||||
func (r Range[C]) Contains(e C) bool { return r.aB(e) && r.bE(e) }
 | 
			
		||||
 | 
			
		||||
// ContainsStrictLeft retourne vrai si e ∈ ]begin;end].
 | 
			
		||||
func (r Range[C]) ContainsStrictLeft(e C) bool { return e.Gt(r.begin) && e.Le(r.end) }
 | 
			
		||||
func (r Range[C]) ContainsStrictLeft(e C) bool { return r.aB(e, true) && r.bE(e) }
 | 
			
		||||
 | 
			
		||||
// ContainsStrictRight retourne vrai si e ∈ [begin;end[.
 | 
			
		||||
func (r Range[C]) ContainsStrictRight(e C) bool { return e.Ge(r.begin) && e.Lt(r.end) }
 | 
			
		||||
func (r Range[C]) ContainsStrictRight(e C) bool { return r.aB(e) && r.bE(e, true) }
 | 
			
		||||
 | 
			
		||||
// ContainsStrict retourne vrai si e ∈ ]begin;end[.
 | 
			
		||||
func (r Range[C]) ContainsStrict(e C) bool { return e.Gt(r.begin) && e.Lt(r.end) }
 | 
			
		||||
func (r Range[C]) ContainsStrict(e C) bool { return r.aB(e, true) && r.bE(e, true) }
 | 
			
		||||
 | 
			
		||||
// IsNow retourne vrai si la période est en cours.
 | 
			
		||||
func (r Range[C]) IsNow() bool { return r.Contains(r.begin.Now()) }
 | 
			
		||||
| 
						 | 
				
			
			@ -89,14 +146,14 @@ func (r Range[C]) IsPast() bool { return r.Before(r.begin.Now()) }
 | 
			
		|||
func (r Range[C]) IsFuture() bool { return r.After(r.begin.Now()) }
 | 
			
		||||
 | 
			
		||||
// BeforeRange retourne vrai si r1 est terminée avant que r2 commence.
 | 
			
		||||
func (r1 Range[C]) BeforeRange(r2 Range[C]) bool { return r1.end.Le(r2.begin) }
 | 
			
		||||
func (r1 Range[C]) BeforeRange(r2 Range[C]) bool { return !r1.end.IsNil() && r2.bB(r1.end) }
 | 
			
		||||
 | 
			
		||||
// AfterRange retourne vrai si r2 est terminée avec que r1 commence.
 | 
			
		||||
func (r1 Range[C]) AfterRange(r2 Range[C]) bool { return r2.BeforeRange(r1) }
 | 
			
		||||
func (r1 Range[C]) AfterRange(r2 Range[C]) bool { return !r1.begin.IsNil() && r2.aE(r1.begin) }
 | 
			
		||||
 | 
			
		||||
// ContainsRange retourne vrai si r2 est intégralement comprise dans r1.
 | 
			
		||||
func (r1 Range[C]) ContainsRange(r2 Range[C]) bool {
 | 
			
		||||
	return r1.begin.Le(r2.begin) && r1.end.Ge(r2.end)
 | 
			
		||||
	return ((r2.begin.IsNil() && r1.begin.IsNil()) || r1.aB(r2.begin)) && ((r2.end.IsNil() && r1.end.IsNil()) || r1.bE(r2.end))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InRange retourne vrai si r2 comprend intégralement r1.
 | 
			
		||||
| 
						 | 
				
			
			@ -104,18 +161,18 @@ func (r1 Range[C]) InRange(r2 Range[C]) bool { return r2.ContainsRange(r1) }
 | 
			
		|||
 | 
			
		||||
// Excludes retourne vrai si r1 et r2 ne se chevauchent pas.
 | 
			
		||||
func (r1 Range[C]) Excludes(r2 Range[C]) bool {
 | 
			
		||||
	return r1.end.Le(r2.begin) || r1.begin.Ge(r2.end)
 | 
			
		||||
	return (!r1.end.IsNil() && r2.bB(r1.end)) || (!r1.begin.IsNil() && r2.aE(r1.begin))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Overlaps retourne vrai si r1 et r2 se chevauchent.
 | 
			
		||||
func (r1 Range[C]) Overlaps(r2 Range[C]) bool {
 | 
			
		||||
	return r1.begin.Lt(r2.end) && r1.end.Gt(r2.begin)
 | 
			
		||||
	return (r1.begin.IsNil() || r2.bE(r1.begin, true)) && (r1.end.IsNil() || r2.aB(r1.end, true))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Intersection retourne la période commune entre deux périodes.
 | 
			
		||||
func (r1 Range[C]) Intersection(r2 Range[C]) (result Option[Range[C]]) {
 | 
			
		||||
	if r1.Overlaps(r2) {
 | 
			
		||||
		result = Some(NewRange(Max(r1.begin, r2.begin), Min(r1.end, r2.end)))
 | 
			
		||||
		result = Some(NewRange(maxB(r1.begin, r2.begin), minE(r1.end, r2.end)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
| 
						 | 
				
			
			@ -123,8 +180,8 @@ func (r1 Range[C]) Intersection(r2 Range[C]) (result Option[Range[C]]) {
 | 
			
		|||
 | 
			
		||||
// Joins retourne la plus grande période contiguë formée par deux périodes.
 | 
			
		||||
func (r1 Range[C]) Joins(r2 Range[C]) (result Option[Range[C]]) {
 | 
			
		||||
	if r1.begin.Le(r2.end) && r1.end.Ge(r2.begin) {
 | 
			
		||||
		result = Some(NewRange(Min(r1.begin, r2.begin), Max(r1.end, r2.end)))
 | 
			
		||||
	if (r1.begin.IsNil() || r2.bE(r1.begin)) && (r1.end.IsNil() || r2.aB(r1.end)) {
 | 
			
		||||
		result = Some(NewRange(minB(r1.begin, r2.begin), maxE(r1.end, r2.end)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
| 
						 | 
				
			
			@ -132,27 +189,37 @@ func (r1 Range[C]) Joins(r2 Range[C]) (result Option[Range[C]]) {
 | 
			
		|||
 | 
			
		||||
// Diff retourne la liste des périodes qui ne se chevauchent pas.
 | 
			
		||||
func (r1 Range[C]) Diff(r2 Range[C]) (result []Range[C]) {
 | 
			
		||||
	if r1.begin.Ne(r2.begin) {
 | 
			
		||||
		begin := Min(r1.begin, r2.begin)
 | 
			
		||||
		var end C
 | 
			
		||||
		if begin.Eq(r1.begin) {
 | 
			
		||||
			end = Min(r1.end, r2.begin)
 | 
			
		||||
		} else {
 | 
			
		||||
			end = Min(r2.end, r1.begin)
 | 
			
		||||
	b1, b2 := minB(r1.begin, r2.begin), maxB(r1.begin, r2.begin)
 | 
			
		||||
	e1, e2 := minE(r1.end, r2.end), maxE(r1.end, r2.end)
 | 
			
		||||
 | 
			
		||||
	if b1.Ne(b2) {
 | 
			
		||||
		e := b2
 | 
			
		||||
		if !e1.IsNil() {
 | 
			
		||||
			e = Min(b2, e1)
 | 
			
		||||
		}
 | 
			
		||||
		result = append(result, NewRange(begin, end))
 | 
			
		||||
		result = append(result, NewRange(b1, e))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r1.end.Ne(r2.end) {
 | 
			
		||||
		end := Max(r1.end, r2.end)
 | 
			
		||||
		var begin C
 | 
			
		||||
		if end.Eq(r1.end) {
 | 
			
		||||
			begin = Max(r1.begin, r2.end)
 | 
			
		||||
		} else {
 | 
			
		||||
			begin = Max(r2.begin, r1.end)
 | 
			
		||||
	if e1.Ne(e2) {
 | 
			
		||||
		b := e1
 | 
			
		||||
		if !b2.IsNil() {
 | 
			
		||||
			b = Max(b2, e1)
 | 
			
		||||
		}
 | 
			
		||||
		result = append(result, NewRange(begin, end))
 | 
			
		||||
		result = append(result, NewRange(b, e2))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String retourne la représentation textuelle de la période.
 | 
			
		||||
func (r Range[C]) String() string {
 | 
			
		||||
	b, e := r.begin.String(), r.end.String()
 | 
			
		||||
	if r.begin.IsNil() {
 | 
			
		||||
		b = "-∞"
 | 
			
		||||
	}
 | 
			
		||||
	if r.end.IsNil() {
 | 
			
		||||
		e = "+∞"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("[%s ; %s]", b, e)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue