vendredi 1 avril 2011

Time, DateTime: Manipulation du temps en Python

Le module time
La gestion du temps est prit en charge par la librairie time.
Cette librairie représente le temps (date/heure) sous forme d'un tuple (struct_time).
Il est possible d'obtenir de l'aide facilement depuis l'interpréteur à l'aide de:

import time
help(time)

Quelques fonctions...
time()
Retourne un float qui représente le temps écoulé (en sec) depuis le 1ier Janvier 1970.
La valeur retournée représente le temps local (et non le temps UTC/GMT).
Cette fonction est fort utile (tout comme clock) pour évaluer des différences de temps.

clock()
Retourne le temps (en sec) écoulé depuis le démarrage du processus.

gmtime()
Retourne un tuple décrivant l'heure UTC (GMT) actuelle.
gmtime(x) permet également de transformer un nombre de secondes en temps UTC.
Notez le tm_wday qui est le jour de la semaine (commence à zéro pour lundi 0=lundi, 1=mardi, 2=mercredi, 3=jeudi, ... 6=dimanche)
mais aussi tm_yday qui le jour de l'année (Julian day entre 1 et 366) fort utile lorsque l'on utilise un logiciel comme JDEwards.
>>> ex: en Belgique, il est 10h24 le 10 mars 2011
>>> time.gmtime()
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=10, tm_hour=9, tm_min=24, tm_sec=32, tm_wday=3, tm_yday=69, tm_isdst=0)

localtime()
Retourne un tuple avec le temps local (en fonction du timezone de la machine).
localtime(x) sert également a transformer un nombre de seconde en temps local.
>>> # Le 10 mars 2011 à 10h26, localtime affiche:
>>> time.localtime()
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=10, tm_hour=10, tm_min=26, tm_sec=7, tm_wday=3, tm_yday=69, tm_isdst=0)

sleep(x)
Effectue une pause de x secondes.

asctime()
asctime "Ascii Time" converti le temps local en string.
asctime(x) converti un time tuple x en string.
Pour des fonctions plus avancées, voir strftime() et strptime().
>>> time.asctime( time.localtime() )
'Thu Mar 10 10:47:35 2011'
>>> time.asctime( time.gmtime() )
'Thu Mar 10 09:47:38 2011'
>>> time.asctime()
'Thu Mar 10 10:47:41 2011'

ctime()
ctime converti le temps local en string comme le fait asctime().
ctime(x) converti le temps x en second en string.
>>> time.ctime()
'Thu Mar 10 10:50:21 2011'
>>> time.ctime( time.time() )
'Thu Mar 10 10:50:25 2011'
>>> time.asctime( time.localtime() )
'Thu Mar 10 10:50:28 2011'

mktime
mktime (make time) convertit un time tuple contenant une date en temps local en seconds.

strftime() et strptime()
strftime (f pour format) permet de transformer un time tuple en date en suivant le format spécifique.
strptime (p pour parse) fait l'opération inverse.
>>> import time
>>> time.asctime( time.localtime() )
'Thu Mar 10 11:15:08 2011'
>>> time.strftime("%a, %d/%m/%Y %H:%M:%S +0000", time.localtime())
'Thu, 10/03/2011 11:15:11 +0000'
>>> time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())
'Thu, 10 Mar 2011 11:15:15 +0000'

Plus d'information sur la string de formatage dans l'article de docs.python.org.

Arithmétique des dates
Voici quelques exemples démontrant l'usage de l'arithmétique sur les dates.

Evaluer le temps écoulé
>>> atime=time.time()
>>> time.sleep(25.0)
>>> btime=time.time()
>>> difftime = btime - atime # display the difference in seconds
>>> time.ctime( difftime ) # display the difference in local time zone
'Thu Jan  1 01:00:52 1970'
>>> # ATTENTION: différence erronée de 1 heure 0 min 52 sec XXXXXXXX ROUGE
>>> # cette erreur est causée par la time zone dans lequel la date UTC 
>>  # est replacée. l'usage de localtime provoquerait le même problème!
>>> time.asctime( time.gmtime(difftime) ) # Difference in UTC time zone
'Thu Jan  1 00:00:52 1970'
>>> # Cette fois-ci la différence est correctement évalué. XXXXX VERT
>>> difftuple = time.gmtime(difftime)
>>> difftuple
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=52, tm_wday=3, tm_yday=1, tm_isdst=0)
>>> print( "la différence est de %i heures %i minutes %i secondes" % ( difftuple.tm_hour, difftuple.tm_min, difftuple.tm_sec) )
la différence est de 0 heures 0 minutes 52 secondes

Datetime module

Implémentation des types datetime, time, date et timedelta permettent l'implémentation et la manipulation rapide des types déjà mentionnés.
Ces types supportent également la manipulations arithmétiques.

>>> now = datetime.date.today()
>>> now.ctime()
'Thu Mar 10 00:00:00 2011'
>>> now2 = datetime.datetime.now()
>>> now2.ctime()
'Thu Mar 10 11:59:44 2011'
>>> # Conversion de la date en datetime
>>> now_datetime = datetime.datetime( now.year, now.month, now.day )
>>> now_datetime 
datetime.datetime(2011, 3, 10, 0, 0)
>>> # Evalutation de la difference
>>> diff = now2 - now_datetime
>>> diff
datetime.timedelta(0, 43184, 75719)
>>> print( "Différence en secondes = %i" % (diff.seconds) )
Différence en secondes = 43184
>>> print( "Différence en jours = %i" % (diff.days) )
Différence en jours = 0
>>> print( "Différence en heures = %i" % (diff.seconds / 3600) )
Différence en heures = 11

plus d'info sur documentation datetime sur docs.python.org

Autres modules
Concernant la manipulation du temps, il faut aussi parler des modules

calendar
Le module calandar contient des fonctions tels que calendar.isleapyear ou des fonctions utilitaires retournant des structures ou bien des formattages de calendrier (par mois).
voir www.tutorialspoint.com/python/python_date_time.htm

dateutil
Disponible par défaut, ce module offre quelques extensions concernant la manipulation des dates.
Il gère entre autre les relativedelta permettant de calculer une date relative, voir même de retrouver le dernier jeudi du mois (voir documentation).
L'on retrouve également rrule qui permet de définir des règles recurrences pour constituer des structures à base de date.
Un MUST pour tout ce qui touche la programmation d'agenda.

Exemple de relativedelta (issus du site http://niemeyer.net/python-dateutil):
>>> from datetime import *; from dateutil.relativedelta import *
>>> import calendar
>>> NOW = datetime.now() # Store some values.
>>> TODAY = date.today()
>>> NOW
datetime.datetime(2003, 9, 17, 20, 54, 47, 282310)
>>> TODAY
datetime.date(2003, 9, 17)
>>> NOW+relativedelta(months=+1) # Next month.
datetime.datetime(2003, 10, 17, 20, 54, 47, 282310)
>>> NOW+relativedelta(months=+1, weeks=+1) # Next month, plus one week.
datetime.datetime(2003, 10, 24, 20, 54, 47, 282310)
>>> TODAY+relativedelta(months=+1, weeks=+1, hour=10) # Next month, plus one week, at 10am.
datetime.datetime(2003, 10, 24, 10, 0)

Exemple de rrule (issus du site issus du site http://niemeyer.net/python-dateutil)
>>> list(rrule(DAILY,
               dtstart=parse("19970902T090000"),
               until=parse("19971224T000000")))
[datetime.datetime(1997, 9, 2, 9, 0),
 datetime.datetime(1997, 9, 3, 9, 0),
 datetime.datetime(1997, 9, 4, 9, 0),
 (...)
 datetime.datetime(1997, 12, 21, 9, 0),
 datetime.datetime(1997, 12, 22, 9, 0),
 datetime.datetime(1997, 12, 23, 9, 0)]

Plus de documentation sur niemeyer.net/python-dateutil

pytz
Module relatif à la gestion des timezones.
PS: Je n'ai pas encore été fureter dedans.

Aucun commentaire: