Je souhaite comparer les horodatages UTC d'un fichier journal avec les horodatages locaux. Lors de la création de l'objet datetime
local, j'utilise quelque chose comme:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
tzinfo=pytz.timezone('Israel'))
Je veux trouver un outil automatique qui remplacerait la tzinfo=pytz.timezone('Israel')
par le fuseau horaire local actuel.
Des idées?
Dans Python 3.x, le fuseau horaire local peut être défini comme suit:
import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
C'est une utilisation délicate de datetime
's code .
comparer les horodatages UTC d'un fichier journal avec les horodatages locaux.
Il est difficile de trouver le nom Olson TZ pour un fuseau horaire local de manière portable. Heureusement, vous n'en avez pas besoin pour effectuer la comparaison.
tzlocal
module retourne un fuseau horaire pytz correspondant au fuseau horaire local:
from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here
Contrairement aux autres solutions présentées jusqu'à présent, le code ci-dessus évite les problèmes suivants:
dateutil
) ne parviennent pas à en tenir compte.Remarque: pour obtenir un objet datetime compatible avec un fuseau horaire à partir d’un objet datetime naïf, vous devez utiliser*:
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
au lieu de:
#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
*is_dst=None
force une exception si l'heure locale donnée est ambiguë ou inexistante.
Si vous êtes certain que tous les horodatages locaux utilisent le même décalage (actuel) utc pour le fuseau horaire local, vous pouvez effectuer la comparaison en utilisant uniquement stdlib:
# convert a naive datetime object that represents time in local timezone to Epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()
# convert a naive datetime object that represents time in UTC to Epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()
timestamp1
et timestamp2
peuvent être comparés directement.
Remarque:
timestamp1
ne fonctionne que si l'offset UTC à Epoch (datetime.fromtimestamp(0)
) est identique à maintenantfromtimestamp()
crée un objet date/heure naïf dans le fuseau horaire local actuelutcfromtimestamp()
crée un objet date/heure naïf au format UTC.Je me demandais la même chose et j'ai trouvé la réponse en 1:
Jetez un coup d’œil à la section 8.1.7: le format "% z" (en minuscule, la majuscule Z renvoie également le fuseau horaire, mais pas au format à 4 chiffres, mais sous la forme d’abréviations de fuseau horaire, comme dans [3]) of strftime renvoie le formulaire "+/- 4DIGIT" standard dans les en-têtes de courrier électronique (voir la section 3.3 de la RFC 2822, voir [2], qui rend obsolètes les autres moyens de spécifier le fuseau horaire des en-têtes de courrier électronique).
Donc, si vous voulez que votre fuseau horaire soit dans ce format, utilisez:
time.strftime("%z")
[1] http://docs.python.org/2/library/datetime.html
[2] http://tools.ietf.org/html/rfc2822#section-3.3
[3] Abréviations de fuseau horaire: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations , uniquement à titre de référence.
Commencez par obtenir les modules pytz et tzlocal
pip install pytz tzlocal
puis
from tzlocal import get_localzone
local = get_localzone()
alors vous pouvez faire des choses comme
from datetime import datetime
print(datetime.now(local))
Basé sur la réponse de J. F. Sebastian , vous pouvez le faire avec la bibliothèque standard:
import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))
Testé en 3.4, devrait fonctionner sur 3.4+
Voici une version légèrement plus concise de la solution de @ vbem:
from datetime import datetime as dt
dt.utcnow().astimezone().tzinfo
La seule différence importante est que j'ai remplacé datetime.datetime.now(datetime.timezone.utc)
par datetime.datetime.utcnow()
. Par souci de brièveté, j'ai aussi aliasé datetime.datetime
en tant que dt
.
Pour mes besoins, je veux le décalage UTC en secondes. Voici à quoi ça ressemble:
dt.utcnow().astimezone().utcoffset().total_seconds()
Voici un moyen d'obtenir le fuseau horaire local en utilisant uniquement la bibliothèque standard (ne fonctionne que dans un environnement * nix):
>>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
Vous pouvez l'utiliser pour créer un fuseau horaire pytz
:
>>> import pytz
>>> my_tz_name = '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>
... que vous pouvez ensuite appliquer à une datetime
:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)
>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>)
Sur la base de la réponse ci-dessus de Thoku, voici une réponse qui résout le fuseau horaire à la demi-heure la plus proche (ce qui est pertinent pour certains fuseaux horaires, par exemple celui de l'Australie méridionale):
from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
Eviter le module non standard (semble être une méthode manquante du module datetime):
from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60 # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60) # we do not handle 1/2 h timezone offsets
print 'Local time offset is %i h to UTC.' % (utcOffset_h)
Pour des raisons simples, vous pouvez utiliser l’implémentation tzinfo
suivante, qui interroge le système d’exploitation sur les décalages de fuseau horaire:
import datetime
import time
class LocalTZ(datetime.tzinfo):
_unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal()
def dst(self, dt):
return datetime.timedelta(0)
def utcoffset(self, dt):
t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone
utc = datetime.datetime(*time.gmtime(t)[:6])
local = datetime.datetime(*time.localtime(t)[:6])
return local - utc
print datetime.datetime.now(LocalTZ())
print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ())
# If you're in the EU, the following datetimes are right on the DST change.
print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is invalid, as the clock moves directly from
# 01:59:59 standard time to 03:00:00 daylight savings time.
print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is ambigous, as 02:00 can be either DST or standard
# time. (It is interpreted as standard time.)
print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ())
Tout d'abord, notez que la question présente une initialisation incorrecte d'un objet datetime conscient:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
... tzinfo=pytz.timezone('Israel'))
crée une instance invalide. On peut voir le problème en calculant le décalage UTC de l'objet résultant:
>>> print(local_time.utcoffset())
2:21:00
(Notez le résultat qui est une fraction d'heure impaire.)
Pour initialiser correctement une date/heure conscient en utilisant pytz, vous devez utiliser la méthode localize()
comme suit:
>>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12))
>>> print(local_time.utcoffset())
3:00:00
Maintenant, si vous avez besoin d’un fuseau horaire pytz local en tant que nouveau tzinfo, vous devez utiliser le paquet tzlocal comme l’ont déjà expliqué d’autres appelez la méthode astimezone()
sans argument pour convertir une instance datetime
au courant en votre fuseau horaire local:
>>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z')
'2010-04-27 05:00 EDT -0400'
Vous pouvez être heureux avec pendule
>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name
'Israel'
Pendulum a une API bien conçue pour manipuler les dates. Tout est conscient de la TZ.
now_dt = datetime.datetime.now()
utc_now = datetime.datetime.utcnow()
now_ts, utc_ts = map(time.mktime, map(datetime.datetime.timetuple, (now_dt, utc_now)))
offset = int((now_ts - utc_ts) / 3600)
j'espère que ceci vous aidera.