Des codes sources perlConsultez toutes les FAQ
Nombre d'auteurs : 13, nombre de questions : 59, dernière mise à jour : 27 mai 2011
- Comment afficher une date en perl ?
- Comment récupérer une date aléatoire entre deux dates données ?
- Comment connaitre le time depuis une date ( L'inverse de localtime et gmtime) ?
- Comment calculer le nombre de jours et/ou semaines entre deux dates ?
- Connaitre une date vieille ou futur
- Comment obtenir la date au format DB2, obtenir la microseconde ?
- Les modules les plus utilisés pour la gestion des dates en perl
Il existe plusieurs fonctions perl permettant d'obtenir la date (année, mois, jour, heure, etc. ).
- time : renvoie un nombre scalaire qui indique le nombre de secondes qui se sont écoulées depuis la date fr epoch de votre machine.
- localtime : renvoie les données relatives au temps local. L'affichage ressemble à celui de la fonction date de linux.
- gmtime : renvoie les données relatives au temps universel.
- Module POSIX.
#
!/usr/bin/perl
use strict;
use warnings;
my $le_time
=
time
;
print
"
Depuis
le
1
/
1
/
1970
,
il
y
a
eu
$
le_time
secondes
.
\n
"
;
my $le_localtime
=
localtime
;
print
"
La
date
locale
:
$
le_localtime
\n
"
;
my $le_gmtime
=
gmtime
;
print
"
La
date
universelle
:
$
le_gmtime
\n
"
;
Depuis le 1/1/1970, il y a eu 1185539208 secondes.
La date locale : Fri Jul 27 14:26:48 2007
La date universelle : Fri Jul 27 12:26:48 2007
localtime(time) renvoie un tableau contenant plusieurs données nécessaires comme le jour, le mois, l'année, etc. Il est plus facile d'expliquer via un exemple. Voici une procédure que j'utilise régulièrement pour afficher la date.
#
!/usr/bin/perl
use strict;
use warnings;
my $RefDateActuelle
=
date(); #
On
recupere
la
réference
d'un
hash
my $time
=
1234567890
;
my $RefAutreDate
=
date($time
); #
On
recupere
la
réference
d'un
hash
print
"
Date
actuelle
:
$
RefDateActuelle
-
>
{
date
}
$
RefDateActuelle
-
>
{
heure
}
\n
"
;
print
"
Date
correspondant
au
time
$
time
:
$
RefAutreDate
>
{
date
}
$
RefAutreDate
>
{
heure
}
\n
"
;
sub
date
{
my $time
=
shift
|
|
time
; #
$time
par
defaut
vaut
le
time
actuel
my ( $seconde
, $minute
, $heure
, $jour
, $mois
, $annee
, $jour_semaine
, $jour_annee
, $heure_hiver_ou_ete
)
=
localtime
($time
);
$mois
+
=
1
;
$annee
+
=
1900
;
#
On
rajoute
0
si
le
chiffre
est
compris
entre
1
et
9
foreach ( $seconde
, $minute
, $heure
, $jour
, $mois
, $annee
) {
s/^(\d)$/0$1/
;
}
my %date
=
(
"
date
"
=
>
"
$
jour
-
$
mois
-
$
annee
"
,
"
heure
"
=
>
"
$
heure
:
$
minute
:
$
seconde
"
,
"
jour_semaine
"
=
>
$jour_semaine
,
"
jour_annee
"
=
>
$jour_annee
,
"
hiverOuEte
"
=
>
$heure_hiver_ou_ete
,
);
return \%date;
}
Date actuelle : 05-12-2008 11:02:57
Date correspondant au time 1234567890 : 14-02-2009 00:31:30
POSIX
use POSIX qw(
strftime
)
;
my $now_string
=
strftime "
%
a
%
b
%
e
%
H
:
%
M
:
%
S
%
Y
"
, localtime
;
Exemple 2 en utilisant le format %V, qui défini le numéro de semaine selon la norme ISO 8601:2000
use POSIX qw(
strftime
)
;
my %jours
=
("
1er
janvier
2009
"
=
>
[ 0
, 0
, 0
, 1
, 0
, 109
],
"
31
décembre
2009
"
=
>
[ 0
, 0
, 0
, 31
, 11
, 109
]);
print
strftime "
Le
$
_
est
en
semaine
%
V
\n
"
, @{
$
jours
{
$
_
}
}
foreach sort
keys
%jours
;
Qui produit :
Le 1er janvier 2009 est en semaine 01
Le 31 décembre 2009 est en semaine 53
Comme DateTime est le module préconisé, mais qu'il n'est pas disponible dans le Core,
alors que POSIX l'est, il me semble que c'est une bonne alternative pour des utilisations "limitées".
Le code ci-dessous est compatible avec des machines acceptant des entiers sur 32 bits. Il
utilise mktime et localtime.
Attention toutefois sur les machines 32 bits, les dates limites utilisables sont de 1904 à 2038.
Pour utiliser des dates en dehors de cette plage, il faut s'en remettre aux modules spécialisés comme DateTime.
Il peut être utile de connaître le time d'une date, c'est l'inverse de time, localtime et gmtime.
Cela se fait par exemple en php pour les connaisseurs via la fonction mktime.
Comme d'habitude, il existe un module Time::LocalTime::Local
en perl déjà présent dans le CORE, donc pas besoin d'installation.
Ce module posséde deux méthodes timelocal et timegm qui renvoient le time.
Il faut leur donner 6 informations sous forme de tableau ($sec,$min,$hour,$mday,$mon,$year).
Attention : $year sera bien l'année classique (avec + 1900),
ex : 2007 et $mois sera compris entre 0 et 11 et non entre 1 et 12.
Nous trouver le time des dates 01/01/2000 et 05/12/2008
#
!/usr/bin/perl
use strict;
use Carp;
use warnings;
use Time::Local;
my @Dates1
=
split
("
/
"
, "
01
/
01
/
2000
"
);
my @Dates2
=
split
("
/
"
, "
05
/
12
/
2008
"
);
#
Reduisons
le
mois
de
1
$Dates1
[1
] -
=
1
;
$Dates2
[1
] -
=
1
;
print
"
01
/
01
/
2000
:
"
, timelocal( 0
,0
,0
, @Dates1
),"
\n
"
;
print
"
05
/
12
/
2008
:
"
, timelocal( 0
,0
,0
, @Dates2
),"
\n
"
;
Vous pourrez maintenant jongler avec les time afin de faire des calculs sur les dates, faires des comparaisons de dates et autres. D'un point pédagogique c'est bien, mais je vous conseille d'utiliser des modules adéquats pour faire cela plus proprement.
01/01/2000 : 946681200
15/12/2008 : 1229295600
Vous souhaitez connaitre le nombre de jours (ou le nombre de semaines) entre deux dates, utilisez le module Date::CalcDate::Calc.
#
!/usr/bin/perl
use warnings;
use strict;
use Date::Calc qw(
:all
)
;
my $date1
=
'
28/05/2006
'
;
my $date2
=
'
19/11/2009
'
;
my ( $jour1
, $mois1
, $annee1
) =
split
( '
/
'
, $date1
);
my ( $jour2
, $mois2
, $annee2
) =
split
( '
/
'
, $date2
);
#
Calcul
le
nombre
de
jour
entre
2
dates
my $NombreJoursEntreDate
=
Delta_Days( ( $annee1
, $mois1
, $jour1
), ( $annee2
, $mois2
, $jour2
) );
print
"
Il
y
a
$
NombreJoursEntreDate
jours
entre
$
date1
et
$
date2
\n
"
;
#
ou
Nombre
de
semaines
et
jours
my $NbrSemaine
=
int
( $NombreJoursEntreDate
/
7
);
my $NbrJourRestant
=
$NombreJoursEntreDate
% 7
;
print
"
Il
y
a
$
NbrSemaine
semaine
(
s
)
et
$
NbrJourRestant
jour
(
s
)
entre
$
date1
et
$
date2
\n
"
;
Il y a 1271 jours entre 28/05/2006 et 19/11/2009
Il y a 181 semaine(s) et 4 jour(s) entre 28/05/2006 et 19/11/2009
Exemple de script permettant de connaitre :
- la date d'aujourd'hui
- la date dans 6 jours
- la date 48 jours avant aujourd'hui
- la date 2 ans et 6 mois avant aujourd'hui
- la date de demain
#
!/usr/bin/perl
use strict;
use warnings;
use Date::Calc qw(
:all
)
;
my $usage
=
<<"FIN_USAGE";
Usage
:
perl
$
0
date
separateur
(
Ex
:
perl
$
0
12
/
05
/
2003
/
)
ou
perl
$
0
FIN_USAGE
my ($jour
,$mois
,$annee
) =
();
if ( @ARGV
=
=
0
) {
($jour
,$mois
,$annee
)=
format_date();
}
elsif ( @ARGV
=
=
2
) {
my ($date
, $separateur
) =
@ARGV
;
chomp
$date
;
chomp
$separateur
;
($jour
,$mois
,$annee
) =
format_date($date
,$separateur
);
}
else {
print
"
$
usage
\n
"
;
exit;
}
#
#############################
print
"
Date
:
$
jour
/
$
mois
/
$
annee
\n
"
;
my ($aa
,$mm
,$jj
,$aaa
,$mmm
,$jjj
) =
();
($aa
,$mm
,$jj
)=
Add_Delta_Days($annee
,$mois
,$jour
,6
);
print
"
6
jours
apres
:
$
jj
/
$
mm
/
$
aa
\n
"
;
($aa
,$mm
,$jj
)=
Add_Delta_Days($annee
,$mois
,$jour
,-
48
);
print
"
48
jours
avant
:
$
jj
/
$
mm
/
$
aa
\n
"
;
($aa
,$mm
,$jj
)=
Add_Delta_YM($annee
,$mois
,$jour
,-
2
,-
6
);
print
"
2
ans
et
6
mois
avant
:
$
jj
/
$
mm
/
$
aa
\n
"
;
($aaa
,$mmm
,$jjj
)=
Add_Delta_Days($annee
,$mois
,$jour
,1
);
print
"
jour
d
'
apres
:
$
jjj
/
$
mmm
/
$
aaa
\n
"
;
sub
format_date
{
my ($date
, $separateur
) =
@_
;
my ($jour
,$mois
,$annee
) =
();
if (defined
$date
) {
($jour
,$mois
,$annee
) =
split
($separateur
,$date
);
return ($jour
,$mois
,$annee
);
}
else {
($jour
,$mois
,$annee
) =
(localtime
)[3
,4
,5
];
$mois
=
$mois
+
1
;
$annee
=
$annee
+
1900
;
#
On
rajoute
0
si
le
chiffre
est
compris
entre
1
et
9
foreach ($jour
,$mois
,$annee
) {
s/^(\d)$/0$1/
;
}
return ($jour
, $mois
, $annee
);
}
}
Voici une procédure pour générer un timestamp au format DB2 c'est à dire au format : AAAA-MM-JJ HH:mm:ss.xxxxxx où les x représentent les microsecondes.
#
!/usr/bin/perl
use strict;
use warnings;
use Time::HiRes;
print
ObtenirDateFormatDB2(),"
\n
"
;
#
------------------------------------------------
#
ObtenirDateFormatDB2
#
But
:
Retourne
un
temps
au
foramt
DB2
#
ex
:
2009-10-25
16:35:53.123456
#
------------------------------------------------
sub
ObtenirDateFormatDB2
{
my ( $epochsecondes
, $microsecondes
) =
Time::HiRes::gettimeofday;
my ( $seconde
, $minute
, $heure
, $jour
, $mois
, $annee
) =
localtime
($epochsecondes
);
$mois
+
=
1
;
$annee
+
=
1900
;
#
On
rajoute
0
si
le
nombre
est
compris
entre
1
et
9
foreach ( $seconde
, $minute
, $heure
, $jour
, $mois
, $annee
, $microsecondes
) {
s{^(\d)$}{0$1}
;
}
return "
$
annee
-
$
mois
-
$
jour
$
heure
:
$
minute
:
$
seconde
.
$
microsecondes
"
;
}
Résultat : 2009-10-23 09:37:52.957328
N'hésitez pas à consulter la documentation du module
Time::HiResTime::HiRes.
Les modules les plus utilisés en perl pour la gestion des dates sont DateTimeDateTime,
Date::ManipDate::Manip,
Date::CalcDate::Calc
et POSIXPOSIX.
DateTime a été fondé afin de rassembler l'ensemble des fonctionnalités en rapport
avec le temps auparavant dispersées sur un grand nombre de module et d'offrir une
interface simple et cohérente à ces fonctionnalités, le tout en gardant des bonnes
performances et un poids très raisonnable. D'après tout ce que j'ai pu essayer avec,
c'est un succès ! Je recommande donc à tous ceux qui veulent manipuler de façon
complexe des dates en Perl de se diriger vers cette distribution, ils sont garantis
d'y trouver ce dont ils ont besoin, et de pouvoir travailler simplement et efficacement avec.
Si une grande majorité de Perliste se met à utiliser DateTime, cela facilitera également
les échanges de code entre utilisateurs du forum. Il est également possible que DateTime
se retrouve intégré au CORE, ce qui faciliterait encore son utilisation et sa diffusion.
Vous êtes bien sûr libre d'utiliser n'importe quel module de gestion de dates (après
tout la philosophie de Perl c'est TIMTOWDI : There's more than one way to do it).