Use Python to find out if a timezone currently in daylight savings time [duplicate] - python

This question already has answers here:
Is a specific timezone using DST right now?
(2 answers)
Closed 8 years ago.
We have a server that runs on GMT time. I need to write a Python script that determines if it's currently (at this very second) Daylight Savings Time (DST) in Los Angeles, CA. How can I accomplish this? I took a look at pytz and time, but I can't figure it out. I realize that I could create some logic such as comparing the current time in LA to GMT time, but it would be a lot cleaner if I could use a standard library instead.
Thanks
Edit: Here's some sample code of me setting up the timezone:
from pytz import timezone
import pytz
from datetime import datetime, timedelta
tz = timezone('America/Los_Angeles')
// Instantiate a datetime object using tz?
Edit: Here's a snippet of code that will work. It's not elegant, which is why I'm asking if there's a library or something that is made for this. Maybe like a is_dst() function.
utc = timezone("UTC")
now = utc.localize(datetime.utcnow())
los_angeles_tz = timezone('America/Los_Angeles')
los_angeles_time = now.astimezone(los_angeles_tz)
delta = los_angeles_time.utcoffset()
dstDelta = timedelta(hours=-8)
is_dst = (delta == dstDelta)

import pytz
from datetime import datetime, timedelta
def is_dst(zonename):
tz = pytz.timezone(zonename)
now = pytz.utc.localize(datetime.utcnow())
return now.astimezone(tz).dst() != timedelta(0)
Usage:
>>> is_dst("America/Los_Angeles")
False
>>> is_dst("America/Sao_Paulo")
True

from datetime import datetime
import pytz
isdst_now_in = lambda zonename: bool(datetime.now(pytz.timezone(zonename)).dst())
Example:
>>> isdst_now_in("America/Los_Angeles") # 2014-10-27 12:32:07 PDT-0700
True
>>> isdst_now_in("Australia/Melbourne") # 2014-10-28 06:32:07 AEDT+1100
True
Here's stdlib-only version on Unix using time.tzset() function:
import os
import time
from contextlib import contextmanager
#contextmanager
def local_timezone(zonename):
#NOTE: it manipulates global state
oldname = os.environ.get('TZ')
try:
os.environ['TZ'] = zonename
time.tzset()
yield
finally:
if oldname is None:
del os.environ['TZ']
else:
os.environ['TZ'] = oldname
time.tzset()
def time_isdst_now_in(zonename):
with local_timezone(zonename):
return time.localtime().tm_isdst > 0
The usage is the same:
>>> time_isdst_now_in('Europe/London') # 2014-04-17 18:42:11 BST+0100
True
Note: time.daylight is not used due to issues in some edge cases.

Related

Python 3 How to format to yyyy-mm-ddThh:mm:ssZ

I'm new to Python and I cannot for the life of me find my specific answer online. I need to format a timestamp to this exact format to include 'T', 'Z' and no sub or miliseconds like this yyyy-mm-ddThh:mm:ssZ i.e. 2019-03-06T11:22:00Z. There's lots of stuff on parsing this format but nothing about formatting this way. The only way I have nearly got it to work involves sub-seconds which I do not need. I've tried using arrow and reading their documentation but unable to get anything to work. Any help would be appreciated.
Try datetime library
import datetime
output_date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
print(output_date)
For more information, refer to the Python Documentation.
Be careful. Just be cause a date can be formatted to look like UTC, doesn't mean it's accurate.
In ISO 8601, 'Z' is meant to designate "zulu time" or UTC ('+00:00'). While local times are typically designated by their offset from UTC. Even worse, these offsets can change throughout a year due to Daylight Saving Time (DST).
So unless you live in England in the winter or Iceland in the summer, chances are, you aren't lucky enough to be working with UTC locally, and your timestamps will be completely wrong.
Python3.8
from datetime import datetime, timezone
# a naive datetime representing local time
naive_dt = datetime.now()
# incorrect, local (MST) time made to look like UTC (very, very bad)
>>> naive_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
'2020-08-27T20:57:54Z' # actual UTC == '2020-08-28T02:57:54Z'
# so we'll need an aware datetime (taking your timezone into consideration)
# NOTE: I imagine this works with DST, but I haven't verified
aware_dt = naive_dt.astimezone()
# correct, ISO-8601 (but not UTC)
>>> aware_dt.isoformat(timespec='seconds')
'2020-08-27T20:57:54-06:00'
# lets get the time in UTC
utc_dt = aware_dt.astimezone(timezone.utc)
# correct, ISO-8601 and UTC (but not in UTC format)
>>> utc_dt.isoformat(timespec='seconds')
'2020-08-28T02:57:54+00:00'
# correct, UTC format (this is what you asked for)
>>> date_str = utc_dt.isoformat(timespec='seconds')
>>> date_str.replace('+00:00', 'Z')
'2020-08-28T02:57:54Z'
# Perfect UTC format
>>> date_str = utc_dt.isoformat(timespec='milliseconds')
>>> date_str.replace('+00:00', 'Z')
'2020-08-28T02:57:54.640Z'
I just wanted to illustrate some things above, there are much simpler ways:
from datetime import datetime, timezone
def utcformat(dt, timespec='milliseconds'):
"""convert datetime to string in UTC format (YYYY-mm-ddTHH:MM:SS.mmmZ)"""
iso_str = dt.astimezone(timezone.utc).isoformat('T', timespec)
return iso_str.replace('+00:00', 'Z')
def fromutcformat(utc_str, tz=None):
iso_str = utc_str.replace('Z', '+00:00')
return datetime.fromisoformat(iso_str).astimezone(tz)
now = datetime.now(tz=timezone.utc)
# default with milliseconds ('2020-08-28T02:57:54.640Z')
print(utcformat(now))
# without milliseconds ('2020-08-28T02:57:54Z')
print(utcformat(now, timespec='seconds'))
>>> utc_str1 = '2020-08-28T04:35:35.455Z'
>>> dt = fromutcformat(utc_string)
>>> utc_str2 = utcformat(dt)
>>> utc_str1 == utc_str2
True
# it even converts naive local datetimes correctly (as of Python 3.8)
>>> now = datetime.now()
>>> utc_string = utcformat(now)
>>> converted = fromutcformat(utc_string)
>>> now.astimezone() - converted
timedelta(microseconds=997)
Thanks to skaul05 I managed to get the code I needed, it's
date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
print(date)
With f strings, you can shorten it down to:
from datetime import datetime
f'{datetime.now():%Y-%m-%dT%H:%M:%SZ}'
Credits go to How do I turn a python datetime into a string, with readable format date?.

Converting Unix timestamps with UTC offset, to Python datetime in different timezones?

If I run the following git log command (here, in this repo: https://github.com/rubyaustralia/rubyconfau-2013-cfp):
$ git --no-pager log --reverse --date=raw --pretty='%ad %h'
1344507869 -0700 314b3d4
1344508222 +1000 dffde53
1344510528 +1000 17e7d3b
...
... I get a list, where I have both Unix timestamp (seconds since Epoch), and a UTC offset, for every commit. What I would like to do, is to obtain a timezone aware datetime, that will:
Show me the date/time as the commit author saw it at the time (as per the recorded UTC time)
Show me the date/time as I would have seen it in my local timezone
In the first case, all I have is a UTC offset, not the author's time zone - and as such I'd have no information about possible daylight savings changes.
In the second case, my OS would most likely be set up to a certain locale including a (geographical) timezone, which would be aware of DST changes; say CET timezone has UTC offset of +0100 in winter, but in the summer daylight saving, it has UTC offset of +0200 (and is then called CEST)
In any case, I'd want to start with a UTC timestamp, because the "1344508222" count of epoch seconds is independent from timezones; the offset +1000 would simply help us see the human-readable output hopefully as the author saw it.
I need to do this for a Python 2.7 project, and I scoured through a ton of resources (SO posts), - and I came up with the following example (which attempts to parse the second line from the above snippet, "1344508222 +1000 dffde53"). However, I'm really not sure if it is right; so ultimately, my question would be - what would be the right way to do this?
Preamble:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import datetime
import pytz
import dateutil.tz
import time
def getUtcOffsetFromString(in_offset_str): # SO:1101508
offset = int(in_offset_str[-4:-2])*60 + int(in_offset_str[-2:])
if in_offset_str[0] == "-":
offset = -offset
return offset
class FixedOffset(datetime.tzinfo): # SO:1101508
"""Fixed offset in minutes: `time = utc_time + utc_offset`."""
def __init__(self, offset):
self.__offset = datetime.timedelta(minutes=offset)
hours, minutes = divmod(offset, 60)
#NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
# that have the opposite sign in the name;
# the corresponding numeric value is not used e.g., no minutes
self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
def utcoffset(self, dt=None):
return self.__offset
def tzname(self, dt=None):
return self.__name
def dst(self, dt=None):
return datetime.timedelta(0)
def __repr__(self):
return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
Start of parsing:
tstr = "1344508222 +1000 dffde53"
tstra = tstr.split(" ")
unixepochsecs = int(tstra[0])
utcoffsetstr = tstra[1]
print(unixepochsecs, utcoffsetstr) # (1344508222, '+1000')
Get UTC timestamp - first I attempted to parse the string 1528917616 +0000 with dateutil.parser.parse:
justthetstz = " ".join(tstra[:2])
print(justthetstz) # '1344508222 +1000'
#print(dateutil.parser.parse(justthets)) # ValueError: Unknown string format
... but that unfortunately fails.
This worked to get UTC timestamp:
# SO:12978391: "datetime.fromtimestamp(self.epoch) returns localtime that shouldn't be used with an arbitrary timezone.localize(); you need utcfromtimestamp() to get datetime in UTC and then convert it to a desired timezone"
dtstamp = datetime.datetime.utcfromtimestamp(unixepochsecs).replace(tzinfo=pytz.utc)
print(dtstamp) # 2012-08-09 10:30:22+00:00
print(dtstamp.isoformat()) # 2012-08-09T10:30:22+00:00 # ISO 8601
Ok, so far so good - this UTC timestamp looks reasonable.
Now, trying to get the date in author's UTC offset - apparently a custom class is needed here:
utcoffset = getUtcOffsetFromString(utcoffsetstr)
fixedtz = FixedOffset(utcoffset)
print(utcoffset, fixedtz) # (600, FixedOffset(600))
dtstampftz = dtstamp.astimezone(fixedtz)
print(dtstampftz) # 2012-08-09 20:30:22+10:00
print(dtstampftz.isoformat()) # 2012-08-09T20:30:22+10:00
This looks reasonable too, 10:30 in UTC would be 20:30 in +1000; then again, an offset is an offset, no ambiguity here.
Now I'm trying to derive the datetime in my local timezone - first, it looks like I shouldn't use the .replace method:
print(time.tzname[0]) # CET
tzlocal = dateutil.tz.tzlocal()
print(tzlocal) # tzlocal()
dtstamplocrep = dtstamp.replace(tzinfo=tzlocal)
print(dtstamp) # 2012-08-09 10:30:22+00:00
print(dtstamplocrep) # 2012-08-09 10:30:22+02:00 # not right!
This doesn't look right, I got the exact same "clock string", and different offsets.
However, .astimezone seems to work:
dtstamploc = dtstamp.astimezone(dateutil.tz.tzlocal())
print(dtstamp) # 2012-08-09 10:30:22+00:00
print(dtstamploc) # 2012-08-09 12:30:22+02:00 # was August -> summer -> CEST: UTC+2h
I get the same with a named pytz.timezone:
cphtz = pytz.timezone('Europe/Copenhagen')
dtstamploc = dtstamp.astimezone(cphtz)
print(dtstamp) # 2012-08-09 10:30:22+00:00
print(dtstamploc) # 2012-08-09 12:30:22+02:00 # is August -> summer -> CEST: UTC+2h
... however, I cannot use .localize here, since my input dtstamp already has a timezone associated with it, and is therefore not "naive" anymore:
# dtstamploc = cphtz.localize(dtstamp, is_dst=True) # ValueError: Not naive datetime (tzinfo is already set)
Ultimately, so far this looks correct, but I'm really uncertain about it - especially since I got to see this:
pytz.astimezone not accounting for daylight savings?
You can't assign the timezone in the datetime constructor, because it doesn't give the timezone object a chance to adjust for daylight savings - the date isn't accessible to it. This causes even more problems for certain parts of the world, where the name and offset of the timezone have changed over the years.
From the pytz documentation:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.
Use the localize method with a naive datetime instead.
... which ended up confusing me: say I want to do this, and I already have a correct timezoned timestamp, - how would I derive a "naive" datetime for it? Just get rid of the timezone info? Or is the right "naive" datetime derived from version of the timestamp expressed in UTC (e.g. 2012-08-09 20:30:22+10:00 -> 2012-08-09 10:30:22+00:00, and so the right "naive" datetime would be 2012-08-09 10:30:22)?

Is there any proper method to convert ISO8601(with tzone) to milliseconds on python? [duplicate]

This question already has answers here:
How do I parse an ISO 8601-formatted date?
(29 answers)
Closed 8 years ago.
The community reviewed whether to reopen this question last month and left it closed:
Original close reason(s) were not resolved
I'm getting a datetime string in a format like "2009-05-28T16:15:00" (this is ISO 8601, I believe). One hackish option seems to be to parse the string using time.strptime and passing the first six elements of the tuple into the datetime constructor, like:
datetime.datetime(*time.strptime("2007-03-04T21:08:12", "%Y-%m-%dT%H:%M:%S")[:6])
I haven't been able to find a "cleaner" way of doing this. Is there one?
I prefer using the dateutil library for timezone handling and generally solid date parsing. If you were to get an ISO 8601 string like: 2010-05-08T23:41:54.000Z you'd have a fun time parsing that with strptime, especially if you didn't know up front whether or not the timezone was included. pyiso8601 has a couple of issues (check their tracker) that I ran into during my usage and it hasn't been updated in a few years. dateutil, by contrast, has been active and worked for me:
from dateutil import parser
yourdate = parser.parse(datestring)
Since Python 3.7 and no external libraries, you can use the fromisoformat function from the datetime module:
datetime.datetime.fromisoformat('2019-01-04T16:41:24+02:00')
Python 2 doesn't support the %z format specifier, so it's best to explicitly use Zulu time everywhere if possible:
datetime.datetime.strptime("2007-03-04T21:08:12Z", "%Y-%m-%dT%H:%M:%SZ")
Because ISO 8601 allows many variations of optional colons and dashes being present, basically CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]. If you want to use strptime, you need to strip out those variations first.
The goal is to generate a UTC datetime object.
If you just want a basic case that work for UTC with the Z suffix like 2016-06-29T19:36:29.3453Z:
datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")
If you want to handle timezone offsets like 2016-06-29T19:36:29.3453-0400 or 2008-09-03T20:56:35.450686+05:00 use the following. These will convert all variations into something without variable delimiters like 20080903T205635.450686+0500 making it more consistent/easier to parse.
import re
# This regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
datetime.datetime.strptime(conformed_timestamp, "%Y%m%dT%H%M%S.%f%z" )
If your system does not support the %z strptime directive (you see something like ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z') then you need to manually offset the time from Z (UTC). Note %z may not work on your system in Python versions < 3 as it depended on the C library support which varies across system/Python build type (i.e., Jython, Cython, etc.).
import re
import datetime
# This regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
# Split on the offset to remove it. Use a capture group to keep the delimiter
split_timestamp = re.split(r"([+|-])",conformed_timestamp)
main_timestamp = split_timestamp[0]
if len(split_timestamp) == 3:
sign = split_timestamp[1]
offset = split_timestamp[2]
else:
sign = None
offset = None
# Generate the datetime object without the offset at UTC time
output_datetime = datetime.datetime.strptime(main_timestamp +"Z", "%Y%m%dT%H%M%S.%fZ" )
if offset:
# Create timedelta based on offset
offset_delta = datetime.timedelta(hours=int(sign+offset[:-2]), minutes=int(sign+offset[-2:]))
# Offset datetime with timedelta
output_datetime = output_datetime + offset_delta
Arrow looks promising for this:
>>> import arrow
>>> arrow.get('2014-11-13T14:53:18.694072+00:00').datetime
datetime.datetime(2014, 11, 13, 14, 53, 18, 694072, tzinfo=tzoffset(None, 0))
Arrow is a Python library that provides a sensible, intelligent way of creating, manipulating, formatting and converting dates and times. Arrow is simple, lightweight and heavily inspired by moment.js and requests.
You should keep an eye on the timezone information, as you might get into trouble when comparing non-tz-aware datetimes with tz-aware ones.
It's probably the best to always make them tz-aware (even if only as UTC), unless you really know why it wouldn't be of any use to do so.
#-----------------------------------------------
import datetime
import pytz
import dateutil.parser
#-----------------------------------------------
utc = pytz.utc
BERLIN = pytz.timezone('Europe/Berlin')
#-----------------------------------------------
def to_iso8601(when=None, tz=BERLIN):
if not when:
when = datetime.datetime.now(tz)
if not when.tzinfo:
when = tz.localize(when)
_when = when.strftime("%Y-%m-%dT%H:%M:%S.%f%z")
return _when[:-8] + _when[-5:] # Remove microseconds
#-----------------------------------------------
def from_iso8601(when=None, tz=BERLIN):
_when = dateutil.parser.parse(when)
if not _when.tzinfo:
_when = tz.localize(_when)
return _when
#-----------------------------------------------
I haven't tried it yet, but pyiso8601 promises to support this.
import datetime, time
def convert_enddate_to_seconds(self, ts):
"""Takes ISO 8601 format(string) and converts into epoch time."""
dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+\
datetime.timedelta(hours=int(ts[-5:-3]),
minutes=int(ts[-2:]))*int(ts[-6:-5]+'1')
seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0
return seconds
This also includes the milliseconds and time zone.
If the time is '2012-09-30T15:31:50.262-08:00', this will convert into epoch time.
>>> import datetime, time
>>> ts = '2012-09-30T15:31:50.262-08:00'
>>> dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1')
>>> seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0
>>> seconds
1348990310.26
Both ways:
Epoch to ISO time:
isoTime = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(epochTime))
ISO time to Epoch:
epochTime = time.mktime(time.strptime(isoTime, '%Y-%m-%dT%H:%M:%SZ'))
Isodate seems to have the most complete support.
aniso8601 should handle this. It also understands timezones, Python 2 and Python 3, and it has a reasonable coverage of the rest of ISO 8601, should you ever need it.
import aniso8601
aniso8601.parse_datetime('2007-03-04T21:08:12')
Here is a super simple way to do these kind of conversions.
No parsing, or extra libraries required.
It is clean, simple, and fast.
import datetime
import time
################################################
#
# Takes the time (in seconds),
# and returns a string of the time in ISO8601 format.
# Note: Timezone is UTC
#
################################################
def TimeToISO8601(seconds):
strKv = datetime.datetime.fromtimestamp(seconds).strftime('%Y-%m-%d')
strKv = strKv + "T"
strKv = strKv + datetime.datetime.fromtimestamp(seconds).strftime('%H:%M:%S')
strKv = strKv +"Z"
return strKv
################################################
#
# Takes a string of the time in ISO8601 format,
# and returns the time (in seconds).
# Note: Timezone is UTC
#
################################################
def ISO8601ToTime(strISOTime):
K1 = 0
K2 = 9999999999
K3 = 0
counter = 0
while counter < 95:
K3 = (K1 + K2) / 2
strK4 = TimeToISO8601(K3)
if strK4 < strISOTime:
K1 = K3
if strK4 > strISOTime:
K2 = K3
counter = counter + 1
return K3
################################################
#
# Takes a string of the time in ISO8601 (UTC) format,
# and returns a python DateTime object.
# Note: returned value is your local time zone.
#
################################################
def ISO8601ToDateTime(strISOTime):
return time.gmtime(ISO8601ToTime(strISOTime))
#To test:
Test = "2014-09-27T12:05:06.9876"
print ("The test value is: " + Test)
Ans = ISO8601ToTime(Test)
print ("The answer in seconds is: " + str(Ans))
print ("And a Python datetime object is: " + str(ISO8601ToDateTime(Test)))

What is the Python equivalent of Javascript's `Date.prototype.toISOString`?

In Javascript, Date.prototype.toISOString gives an ISO 8601 UTC datetime string:
new Date().toISOString()
// "2014-07-24T00:19:37.439Z"
Is there a Python function with behavior that matches Javascript's?
Attempts:
Python's datetime.datetime.isoformat is similar, but not quite the same:
datetime.datetime.now().isoformat()
// '2014-07-24T00:19:37.439728'
Using pytz I can at least make UTC explicit:
pytz.utc.localize(datetime.now()).isoformat())
// '2014-07-24T00:19:37.439728+00:00'
You can use this code:
import datetime
now = datetime.datetime.now()
iso_time = now.strftime("%Y-%m-%dT%H:%M:%SZ")
This did it for me, just using python's standard library:
from datetime import datetime, timezone
def isoformat_js(dt: datetime):
return (
dt.astimezone(timezone.utc)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z")
)
isoformat_js(datetime(2014, 7, 24, 0, 19, 37, 439000))
# => '2014-07-24T00:19:37.439Z'
I attempted to format the string to exactly how it is in the javascript output.
from datetime import datetime
def iso_format(dt):
try:
utc = dt + dt.utcoffset()
except TypeError as e:
utc = dt
isostring = datetime.strftime(utc, '%Y-%m-%dT%H:%M:%S.{0}Z')
return isostring.format(int(round(utc.microsecond/1000.0)))
print iso_format(datetime.now())
#"2014-07-24T00:19:37.439Z"
Using f-strings in Python 3.6+
from datetime import datetime
f'{datetime.now():%Y-%m-%dT%H:%M:%SZ}'
# Used dateutil package from https://pypi.org/project/python-dateutil/
import datetime
import dateutil.tz
def iso_format(dt):
try:
utc_dt = dt.astimezone(dateutil.tz.tzutc())
except ValueError:
utc_dt = dt
ms = "{:.3f}".format(utc_dt.microsecond / 1000000.0)[2:5]
return datetime.datetime.strftime(utc_dt, '%Y-%m-%dT%H:%M:%S.{0}Z'.format(ms))
Is there a Python function with behavior that matches Javascript's?
Not in the standard library, but you could build your own.
The issue is ISO 8601 date format itself allows for two things:
Use of either 'Z' or '+00:00' to represent UTC as used by javascript and python respectively
Number of digits in the decimal fraction of a second is not limited. So, python uses 6 (microsecond precision) and javascript uses 3 (millisecond precision)
So, both are correct and we need to handle the conversion with one or more of the tricks above. I use the following:
Python date object to javascript ISO format string:
pyDateObj = datetime.now() jsISOTimeStr = pyDateObj.astimezone(pytz.timezone("UTC")).isoformat()[:-9] + 'Z'
Javascript date object to python ISO format string:
In javascript:
const jsDateObj = new Date(); jsISOTimeStr = date.toISOString()
Later, in python:
pyDateObj = datetime.fromisoformat(jsISOTimeStr [:-1]+'000+00:00')
you may also use:
import datetime
nowinIsoFromat = datetime.datetime.now().isoformat("T", "milliseconds") + 'Z'

In Python: check if file modification time is older than a specific datetime

I wrote this code in c# to check if a file is out of date:
DateTime? lastTimeModified = file.getLastTimeModified();
if (!lastTimeModified.HasValue)
{
//File does not exist, so it is out of date
return true;
}
if (lastTimeModified.Value < DateTime.Now.AddMinutes(-synchIntervall))
{
return true;
} else
{
return false;
}
How do I write this in python?
I tried this in python.
statbuf = os.stat(filename)
if(statbuf.st_mtime < datetime.datetime.now() - self.synchIntervall):
return True
else:
return False
I got the following exception
message str: unsupported operand type(s) for -: 'datetime.datetime' and 'int'
You want to use the os.path.getmtime function (in combination with the time.time one). This should give you an idea:
>>> import os.path as path
>>> path.getmtime('next_commit.txt')
1318340964.0525577
>>> import time
>>> time.time()
1322143114.693798
#E235's comment in the accepted answer worked really well for me.
Here it is formatted;
import os.path as path
import time
def is_file_older_than_x_days(file, days=1):
file_time = path.getmtime(file)
# Check against 24 hours
return ((time.time() - file_time) / 3600 > 24*days)
Here is a generic solution using timedelta, that works for seconds, days, months and even years...
from datetime import datetime
def is_file_older_than (file, delta):
cutoff = datetime.utcnow() - delta
mtime = datetime.utcfromtimestamp(os.path.getmtime(file))
if mtime < cutoff:
return True
return False
This can be used as follows.
To detect a file older than 10 seconds:
from datetime import timedelta
is_file_older_than(filename, timedelta(seconds=10))
To detect a file older than 10 days:
from datetime import timedelta
is_file_older_than(filename, timedelta(days=10))
If you are ok installing external dependencies, you can also do months and years:
from dateutil.relativedelta import relativedelta # pip install python-dateutil
is_file_older_than(filename, relativedelta(months=10))
The problem there is that your synchIntervall is not a datetime object so Python can't decrease it. You need to use another datetime object.
like:
synchIntervall = datetime.day(2)
or
synchIntervall = datetime.hour(10)
or a more complete one:
synchIntervall = datetime.datetime(year, month, day, hour=0, minute=0, second=0)
the first three are required.
This way you determinate the variable in a value which can be calculated with the datetime.datetime.now() value.

Categories