Code : Tout sélectionner
; Calendrier presque perpétuel
EnableExplicit
Enumeration Fenetres
#Fenetre_principale
EndEnumeration
Enumeration Gadgets
#Str_Jour
#Str_Mois
#Str_Annee
#Txt_Jour
#Txt_Mois
#Txt_Annee
#Txt_Resultat
#Police
#Police2
EndEnumeration
Global X, Police, Police2, a.s, m.s, j.s, JS.s, Mois.s
Define.i Event, EventWindow, EventGadget
;- Constantes et Globales
#SecsParJour = 86400 ; Secondes par jour
#AnneeEpoque = 1601 ; Première année valable pour la plupart des routines date
#JoursJusqu_a_1970 = 134774 ; Jours à compter de la première journée de l'année époque (01-Jan-1601) au 01-Jan-1970
Global ML_Unite_Date.q = 10000000 ; granularité, initialement 1 seconde pour la compatibilité avec les routines date de PB 4.xx
Global ML_Unite_Jour.q = 10000000 * #SecsParJour / ML_Unite_Date ; granularité nombre d'unités par jour
Procedure.q ML_Date(Annee = 0, Mois = 0, Jour = 0, Heure = 0, Minute = 0, Seconde = 0)
; Retourne une date/heure du calendrier julien donnée d'une date/heure du calendrier grégorien
; Retourne la date Julienne/heure locale pour aujourd'hui, si aucun argument n'est donné
; Retourne -1 si l'année est hors de portée
Protected date.q, hs.SYSTEMTIME
If Annee | Mois | Jour | Heure | Minute | Seconde = 0
GetLocalTime_(@hs) ; Heure locale
Else
If Annee = 0 ; Si seulement l'heure est spécifiée
Annee = #AnneeEpoque
Mois = 1
Jour = 1
ElseIf Annee < #AnneeEpoque Or Annee > 9999
ProcedureReturn -1
Else
If Mois = 0
Mois = 1
EndIf
If Jour = 0
Jour = 1
EndIf
EndIf
With hs
\wYear = Annee
\wMonth = Mois
\wDay = Jour
\wHour = Heure
\wMinute = Minute
\wSecond = Seconde
EndWith
EndIf
SystemTimeToFileTime_(@hs, @date) ; Heure locale
ProcedureReturn (date + ML_Unite_Date / 2) / ML_Unite_Date
EndProcedure
Procedure.q ML_Aujourd_hui()
; Retourne la date julienne pour minuit au début d'aujourd'hui
ProcedureReturn ML_Date() / ML_Unite_Jour * ML_Unite_Jour
EndProcedure
Procedure.i ML_Jds(date.q = -1)
; Retourne le jour de la semaine en nombre:
; 0=Dim 1=Lun 2=Mar 3=Mer 4=Jeu 5=Ven 6=Sam
; S'il n'y a pas d'argument, le jour courant est renvoyé
If date < 0
date = ML_Date()
EndIf ; Aujourd'hui
ProcedureReturn Mod((date / ML_Unite_Jour + 1), 7) ; Comme 01-Jan-1601 C'était un lundi
EndProcedure
ProcedureDLL ML_Amj(date.q, *Annee, *Mois, *Jour, *Heure=0, *Minute=0, *Seconde=0)
; Retourne (dans les arguments) une date du calendrier grégorien donnée, en une date julienne
; Si la date est négative, la date/heure locale pour ML_Aujourd_hui() est retournée
; si la date est trop grande, le dernier instant de l'année 9999 est retourné
; L'inverse de la routine ML_Date()
Protected datemax.q = 2650467743999999999 ; 31/12/9999
Protected hs.SYSTEMTIME
If date < 0 ; Supposons maintenant
GetLocalTime_(@hs)
Else
date * ML_Unite_Date
If date > datemax
date = datemax
EndIf
FileTimeToSystemTime_(@date, @hs)
EndIf
With hs
PokeI(*Annee, \wYear)
PokeI(*Mois, \wMonth)
PokeI(*Jour, \wDay)
If *Heure
PokeI(*Heure, \wHour)
EndIf
If *Minute
PokeI(*Minute, \wMinute)
EndIf
If *Seconde
PokeI(*Seconde, \wSecond)
EndIf
EndWith
EndProcedure
ProcedureDLL.i ML_Annee(date.q = -1)
; Retourne la valeur de l'année (#AnneeEpoque..9999) de la date donnée
; S'il n'y a aucun argument, l'année en cours est retournée
Protected a, m, j
ML_Amj(date, @a, @m, @j)
ProcedureReturn a
EndProcedure
ProcedureDLL.i ML_Mois(date.q = -1)
; Renvoie le mois (1 .. 12) dans l'année pour la date donnée
; S'il n'y a aucun argument, le mois en cours est retourné
Protected a, m, j
ML_Amj(date, @a, @m, @j)
ProcedureReturn m
EndProcedure
ProcedureDLL.b ML_Bissextile(Annee = -1)
; Retourne Vrai si l'année est une année bissextile (366 jours)
; S'il n'y a aucun argument, l'année en cours est utilisée
; Dans le calendrier grégorien, l'année bissextile est
; toute année divisible par 4, sauf
; année du centenaire non divisible par 400
; L'année équinoxe de printemps est d'environ 365.242374 jours longs (et croissants)
If Annee <= 0
Annee = ML_Annee()
EndIf ; Cette année
If (Mod(Annee, 4) = 0 And Mod(Annee, 100) <> 0) Or (Mod(Annee, 400) = 0)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
ProcedureDLL.i ML_JoursDansMois(Annee = -1, Mois = -1)
; Retourne le nombre de jours dans le mois donné (28 .. 31)
; Si l'année est absente, l'année en cours est utilisée
; Si l'année est présente, mais le mois absent, février est utilisé
; Si l'année et le mois sont tous deux absents, le mois courant de l'année en cours est utilisé
Protected Jours
If Annee <= 0
Annee = ML_Annee()
If Mois <= 0
Mois = ML_Mois()
EndIf
Else
If Mois <= 0
Mois = 2
EndIf
EndIf
If Mois = 2
Jours = 28 + ML_Bissextile(Annee)
Else
Jours = 31 - $A55 >> Mois & 1
EndIf
ProcedureReturn Jours
EndProcedure
Procedure.s ML_Jds_(date.q = -1)
;Retourne le jour de la semaine en texte:
; 0 = dimanche, 1 = lundi, ... , 6 = samedi
; S'il n'y a pas d'argument, le jour courant est renvoyé
If date < 0
date = ML_Date()
EndIf ; Aujourd'hui
Js = StringField("dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", ML_Jds(ML_Date(Val(a), Val(m), Val(j)))+1,",")
ProcedureReturn Js
EndProcedure
Procedure.s ML_Mois_(date.q=-1)
; Renvoie le mois (1 .. 12) dans l'année pour la date donnée
If date < 0
date = ML_Date()
EndIf ; Aujourd'hui
Select date
Case 1
Mois = "Janvier"
Case 2
Mois = "Février"
Case 3
Mois = "Mars"
Case 4
Mois = "Avril"
Case 5
Mois = "Mai"
Case 6
Mois = "Juin"
Case 7
Mois = "Juillet"
Case 8
Mois = "Août"
Case 9
Mois = "Septembre"
Case 10
Mois = "Octobre"
Case 11
Mois = "Novembre"
Case 12
Mois = "Décembre"
EndSelect
ProcedureReturn Mois
EndProcedure
Procedure Clic_Jour()
If Val(GetGadgetText(#Str_Jour)) > ML_JoursDansMois(Val(GetGadgetText(#Str_Annee)),Val(GetGadgetText(#Str_Mois)))
SetGadgetText(#Str_Jour, "")
SetGadgetText(#Txt_Resultat, "Date non valide")
EndIf
EndProcedure
Procedure Ouvrir_Fenetre_principale()
OpenWindow(#Fenetre_principale, #PB_Ignore, #PB_Ignore, 470, 200, "Calendrier perpétuel 01/01/1601 -> 31/12/9999",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
TextGadget(#Txt_Jour, 5, 10, 70, 40, "Jour")
StringGadget(#Str_Jour, 80, 10, 50, 40, "")
TextGadget(#Txt_Mois, 130, 10, 80, 40, "Mois")
StringGadget(#Str_Mois, 210, 10, 50, 40, "")
TextGadget(#Txt_Annee, 260, 10, 100, 40, "Année")
StringGadget(#Str_Annee, 360, 10, 100, 40, "")
TextGadget(#Txt_Resultat, 10, 100, 440, 80, "")
BindGadgetEvent(#Str_Jour,@Clic_Jour())
Police = LoadFont(#Police, "DejaVu Sans Mono", 24, #PB_Font_Bold)
For X = #Str_Jour To #Txt_Annee
SetGadgetFont(X, Police)
Next
Police2 = LoadFont(#Police2, "DejaVu Sans Mono", 12, #PB_Font_Bold)
SetGadgetFont(#Txt_Resultat, Police2)
SendMessage_(GadgetID(#Str_Jour), #EM_SETLIMITTEXT, 2, 0) ; seulement 2 chiffres pour le jour
SendMessage_(GadgetID(#Str_Mois), #EM_SETLIMITTEXT, 2, 0) ; Idem pour le mois
SendMessage_(GadgetID(#Str_Annee), #EM_SETLIMITTEXT, 4, 0) ; limité à 4 chiffres pour l'année
SetActiveGadget(#Str_Annee)
EndProcedure
Ouvrir_Fenetre_principale()
;- Boucle principale
Repeat
Event = WaitWindowEvent()
Select Event
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Case #PB_Event_Gadget
EventGadget = EventGadget()
If Len(GetGadgetText(#Str_Annee)) = 4 And EventType() = #PB_EventType_Change
SetActiveGadget(#Str_Mois)
EndIf
If Len(GetGadgetText(#Str_Mois)) = 2 And EventType() = #PB_EventType_Change
SetActiveGadget(#Str_Jour)
EndIf
a = GetGadgetText(#Str_Annee)
m = GetGadgetText(#Str_Mois)
j = GetGadgetText(#Str_Jour)
ML_Jds_()
ML_Mois_(Val(m))
If GetGadgetText(#Str_Jour) <> "" And GetGadgetText(#Str_Mois) <> "" And Val(GetGadgetText(#Str_Annee)) > 1600
If ML_Date(Val(a), Val(m), Val(j)) < ML_Aujourd_hui()
SetGadgetText(#Txt_Resultat, "le "+j+" "+Mois+" "+a+" était un "+Js)
ElseIf Val(GetGadgetText(#Str_Jour)) = Day(Date()) And
Val(GetGadgetText(#Str_Mois)) = Month(Date()) And
Val(GetGadgetText(#Str_Annee)) = Year(Date())
SetGadgetText(#Txt_Resultat, "le "+j+" "+Mois+" "+a+" est un "+Js)
Else
SetGadgetText(#Txt_Resultat, "le "+j+" "+Mois+" "+a+" sera un "+Js)
EndIf
EndIf
Case #PB_Event_CloseWindow
EventWindow = EventWindow()
If EventWindow = #Fenetre_principale
CloseWindow(#Fenetre_principale)
Break
EndIf
EndSelect
ForEver
End