Getting astimezone error in linux machine - python

I am using linux aws machine and there is a timezone difference when I do datetime.datetime.now. So I have tried this method to overcome the timezone error
format = "%Y-%m-%d %H:%M:%S %Z%z"
current_date = datetime.datetime.now()
now_asia = current_date.astimezone(timezone('Asia/Kolkata'))
print(now_asia.strftime(format))
when I do my window machine I didnt get any error. The same lines when I use in my linux machine I am getting "ValueError: astimezone() cannot be applied to a naive datetime"
To debug this I tried the methods which is mentioned in this link
pytz and astimezone() cannot be applied to a naive datetime
when I tried the first answer I am not getting any error but the timezone is not converted.
when I tried the second answer I am getting an error 'AttributeError: 'module' object has no attribute 'utcnow'
I tried this
>>>loc_date = local_tz.localize(current_date)
>>> loc_date
datetime.datetime(2020, 4, 6, 7, 23, 36, 702645, tzinfo=<DstTzInfo 'Asia/Kolkata' IST+5:30:00 STD>)
>>> loc_date.strftime(format)
'2020-04-06 07:23:36 IST+05:30'
I am getting this ,so according to indian time if we add 5:30 it will be correct. How should i do it.

Please check that you are indeed running the Python 3.7 interpreter in the cloud. Citing the documentation for the astimezone() function:
Changed in version 3.6: The astimezone() method can now be called on naive instances that are presumed to represent system local time.
Indeed, I just tested the script using Python 3.5.9 and pytz 2019.3 and I get
File "timez.py", line 6, in <module>
now_asia = current_date.astimezone(timezone('Asia/Kolkata'))
ValueError: astimezone() cannot be applied to a naive datetime
But when using Python 3.7.6 on an Amazon Linux 2 AMI instance, the code runs correctly.
Nevertheless, I would suggest to use timezone-aware datetimes from the start.
In the code you're referencing, you're getting that there's no utcnow attribute because that code imports from datetime import datetime, while you're doing import datetime. To make it work, you would use
now_utc = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
But note that the Python documentation now suggests you to use the tz parameter in datetime.now:
import datetime
import pytz
now_utc = datetime.datetime.now(tz=pytz.utc)
local_tz = pytz.timezone('Asia/Kolkata')
now_asia = now_utc.astimezone(local_tz)
format = "%Y-%m-%d %H:%M:%S %Z%z"
print(now_asia.strftime(format))
which prints 2020-04-22 09:25:21 IST+0530 in my case.

Related

How to get local time in python

How could I get the local time, like right now its 9:06
For my friends, Its 6:06.
How could I get that time In python.
I have tried using DateTime but have had no luck finding a way to do this.
You can use pytz library.
from datetime import datetime
import pytz
datetime_NewYork = datetime.now(pytz.timezone('America/New_York'))
print("NY time:", datetime_NewYork.strftime("%H:%M:%S"))
datetime_London = datetime.now(pytz.timezone('Europe/London'))
print("London time:", datetime_London.strftime("%H:%M:%S"))
You can use time library, and localtime()/asctime() function.
import time
# This will give you o/p in the format of
# time.struct_time(tm_year=2022, tm_mon=1, tm_mday=16, tm_hour=19, tm_min=14, tm_sec=39, tm_wday=6, tm_yday=16, tm_isdst=0)
print(time.localtime())
# This will give you o/p in more simpler manner
# 'Sun Jan 16 19:15:01 2022'
print(time.asctime())
You can also use time.time(), but you have to do conversion afterwards.
According to python docs both methods of the datetime module:
import datetime
print(datetime.datetime.today()) # method 1
print(datetime.datetime.now()) # method 2
return the local time (time according to your current time on the machine you are running this code)
The 1st method uses only local time. The 2nd method gives you the ability to pass the optional argument tz which allows you to specify the timezone. But in order to do so, you will need to install a timezone library for python and import it into your code. For example - the abovementioned pytz.
Here is the terminal command for installing pytz library:
sudo -H pip install pytz
Here is an amazing youtube tutorial about the datetime module:
https://www.youtube.com/watch?v=eirjjyP2qcQ&t=855s
Here is the python docs page dedicated to the datetime module:
https://docs.python.org/3/library/datetime.html
May be this could help.
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Current Time =", current_time)
time.localtime() returns the local time.

set a datetime with a specific timezone

I have a script on Heroku, hence I do not know where it resides every time it reboots (-> I cannot manually set the datetime.timedelta), and I need to run a routine at 5pm Rome time. This script has always worked, at least this winter, but now it's starting one hour later, so at 6pm.
import datetime
import pytz
tz = pytz.timezone("Europe/Rome")
now = datetime.datetime.now(tz=tz)
start = datetime.datetime(now.year, now.month, now.day, hour=17, tzinfo=tz)
This answer shows that
using the tzinfo argument of the standard datetime constructors 'does not work' with pytz for many timezones
so I tried refactoring using tz.localize(start), but on the first reboot the system scheduled the routine at 3pm, two hours before. I'm getting very confused: how can I set a specific time in a specific timezone?
Since I needed to solve this problem quickly, I just accepted the tip #MrFuppes gave me to upgrade the version of Python to 3.9 and since I was using 3.7 this wasn't a big deal, at least for my dependencies.
Using ZoneInfo:
from zoneinfo import ZoneInfo
import datetime
tz = ZoneInfo("Europe/Rome")
now = datetime.datetime.now(tz=tz)
start = datetime.datetime(now.year, now.month, now.day, hour=17, tzinfo=tz)

Python - time.time() and datetime.datetime.utcnow().timestamp() returning different Epochs

This is really two questions:
1st, are Epoch (Unix) timestamps the same on all machines (assuming their system clocks are correct), regardless of timezones?
I ask because I have code deployed to AWS Lambda that generates Epoch timestamps using the datetime module. When we extract the data, I am trying to convert to a local time string (also using datetime) and I am getting a 2 hour difference to what was expected. I then started testing the following code:
import datetime
import time
print(time.time()) #1
print(datetime.datetime.utcnow().timestamp()) #2
print#1: 1554747526.775873
print#2: 1554783526.775873
Running on my local machine, they are different by two hours. I deployed the above code to AWS Lambda and they return the same values. How is it different on my machine? The screenshot below shows the same code running on AWS Lambda (left) and my local machine. My system clock is correct.
The reason has to do with the timezone of your computer. The library time uses the timezone set in your computer, but in the case of the datetime library you're using the UTC timezone. In order to obtain the timestamp in the same timezone use datetime.datetime.now().timestamp()
The issue was the ".timestamp()" function.
If I run "datetime.datetime.utcnow()" on AWS, my local machine (and the various test machines I also have (EC2 AWS instances)) they return the same value. The ".timestamp()" function is causing the change.
Also, time.time() apparently only returns time since Epoch. "... this is platform-specific. A platform can return anything it wants for time, as long as it does so in a way that makes localtime and gmtime work properly. That being said, it's usually going to be GMT—or, rather, either UTC (Windows), or UTC-except-for-leap-seconds (most other platforms)."
See: Does Python's time.time() return a timestamp in UTC?
Let's compare calls at local PC and server at Digital Ocean.
datetime.now() - have difference at 3 hours on PC and server;
datetime.utcnow() - equal on both machine;
BUT
datetime.utcnow().timestamp() - have difference at 10800 seconds!!!
# local machine (Win64) UTC+0
>>> datetime.now(), datetime.utcnow(), datetime.utcnow().timestamp()
(datetime.datetime(2019, 8, 2, 22, 13, 39, 535678), # datetime.now()
datetime.datetime(2019, 8, 2, 19, 13, 39, 535678), # datetime.utcnow()
1564762419.535678) # datetime.utcnow().timestamp()
# server(Ubuntu 18) UTC+2.0
>>> datetime.now(), datetime.utcnow(), datetime.utcnow().timestamp()
(datetime.datetime(2019, 8, 2, 19, 13, 39, 253675), # datetime.now()
datetime.datetime(2019, 8, 2, 19, 13, 39, 253691), # datetime.utcnow()
1564773219.253692) # datetime.utcnow().timestamp()
According to the docu on timestamp(), it seems that utcnow() and now() return "naive" instead of "aware" datetimes. I imagine it means they're unaware of what the timezone is or something of the sort.
Their solution seems to be to call timestamp on a datetime with set timezone :
datetime.datetime.utcnow().replace(tzinfo= datetime.timezone.utc).timestamp()
datetime.datetime.now().replace(tzinfo= datetime.timezone.utc).timestamp()
The first is equivalent to time.time().
The second will return the timestamp equivalent to your timezone.
Although datetime.datetime.utcnow() returns a datetime object with the current UTC time, the object returned is timezone naive, i.e. the object doesn't have any timezone info attached.
Example:
>>> datetime.datetime.utcnow()
datetime.datetime(2022, 12, 9, 11, 12, 33, 442103) # no timezone info
Without the timezone info, it is just a regular datetime object. By looking at the object, there is no way to tell whether this time is local time or UTC time.
When you call .timestamp() method on a datetime object, it assumes it to be in your local time and then returns the timestamp.
Better way to get UTC timestamps is like this:
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2022, 12, 9, 11, 12, 33, 442103, tzinfo=timezone.utc)
As you can see, this time the object has a timezone attached. Now, if you call .timestamp() method on it, you'll get the timestamp in UTC.

Get system local timezone in python

Seems strange, but I cannot find an easy way to find the local timezone using pandas/pytz in Python.
I can do:
>>> pd.Timestamp('now', tz='utc').isoformat()
Out[47]: '2016-01-28T09:36:35.604000+00:00'
>>> pd.Timestamp('now').isoformat()
Out[48]: '2016-01-28T10:36:41.830000'
>>> pd.Timestamp('now').tz_localize('utc') - pd.Timestamp('now', tz='utc')
Out[49]: Timedelta('0 days 01:00:00')
Which will give me the timezone, but this is probably not the best way to do it...
Is there a command in pytz or pandas to get the system time zone? (preferably in python 2.7 )
I don't think this is possible using pytz or pandas, but you can always install python-dateutil or tzlocal:
from dateutil.tz import tzlocal
datetime.now(tzlocal())
or
from tzlocal import get_localzone
local_tz = get_localzone()
time.timezone should work.
The offset of the local (non-DST) timezone, in seconds west of UTC
(negative in most of Western Europe, positive in the US, zero in the
UK).
Dividing by 3600 will give you the offset in hours:
import time
print(time.timezone / 3600.0)
This does not require any additional Python libraries.
I have found that in many cases this works: (Since Python 3.6)
from datetime import datetime
# use this extension and it adds the timezone
tznow = datetime.now().astimezone()
print(tznow.isoformat())
2020-11-05T06:56:38.514560-08:00
# It shows that it does have a valid timezone
type(tznow.tzinfo)
<class 'datetime.timezone'>
I find this handy as it does not depend on external packages. It appears to work only in Python3 (but not in Python2)
Quite a few locale time related settings from OS level is covered by time module
import time
# Since Python 3.3
local_time = time.localtime() # returns a `time.struct_time`
tzname_local = local_time.tm_zone # 'EST'
dst = local_time.tm_isdst # _from docs_: may be set to 1 when daylight savings time is in effect,
# and 0 when it is not. A value of -1 indicates that this is not known,
# and will usually result in the correct state being filled in.
tm_gmtoff and tm_zone attributes are available on platforms with C library supporting the corresponding fields in struct tm.
see: https://docs.python.org/3/library/time.html#time.struct_time
# At least from Python 2.7.18
local_tzname = time.tzname # 'EST'
A tuple of two strings: the first is the name of the local non-DST timezone, the second is the name of the local DST timezone. If no DST timezone is defined, the second string should not be used.
see: https://docs.python.org/2.7/library/time.html#time.tzname)
Another trick is to use datetime.now().astimezone() as found here and the reason why it fails on python 2.x
from datetime import datetime
# Python 3 will return a datetime with local timezone,
local_now = datetime.now().astimezone()
# Doesn't work on python 2.x
# datetime.now().astimezone() -> TypeError: Required argument 'tz' (pos 1) not found
# datetime.now().astimezone(dateutil.tz.UTC) -> ValueError: astimezone() cannot be applied to a naive datetime
local_tz = local_now.tzinfo # datetime.timezone
local_tzname = local_tz.tzname(local_now)
print(local_tzname)
While it doesn't use pytz/Pandas, the other answers don't either, so I figured I should post what I'm using on mac/linux:
import subprocess
timezone = subprocess.check_output("date +%Z")
Benefits over the other answers: respects daylight savings time, doesn't require additional libraries to be installed.

How to create a unified unix-timestamp both on iOS and Python?

I am developing an iOS application that needs to sync with a Python based REST service on GAE.
In the python backend I create my timestamps like this:
def create_timestamp(date):
midnight = datetime.time(0)
date_midnight_time = datetime.datetime.combine(date.date(), midnight)
return calendar.timegm(date_midnight_time.utctimetuple())
I pass in the function above datetime.datetime.today(). This would return for 27 Oct 2013 00:00:00 the value 1382832000.
On iOS there is a buildin function for that:
nextDate is set to today's date a bit complicated due an algorithm:
NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:date];
[components setDay:27];
NSDate *nextDate = [calendar dateFromComponents:components];
[nextDate timeIntervalSince1970] which returns for 2013-10-27 00:00:00 BST the value 1382828400.000000
There is some discrepancy though.
Maybe its because that Python side is UTC and iOS shows the time in BST by default and I need to address that. As of last night the British Summer time is no more, but iOS still reports BST. Thats confusing though as a NSDate object is always in UTC from my understanding....
Once its working, is it safe to cast the iOS double
value to int, in order to get a round integer number similar to the Python side?
I know this is old, but I thought I'd respond, since this particular issue is something I've been looking for an answer for for a while:
The IOS timestamp you give refers to the correct midnight for GMT of that date.
The python timestamp you give refers to one hour earlier (11:00 pm on the prior day).
This took me forever to find, and it's a pretty smart way of doing it (particularly when you consider the many more circuitous options I've seen):
I tried this, and it works nicely when trying to get the timestamp for a datetime in your local zone (but..):
from datetime import datetime
def dt_to_timestamp(dt_object):
"""Not really a good, universal solution"""
return eval(dt_object.strftime('%s.%f'))
dt_to_timestamp(datetime.now()) - time.time()
# -0.0002155303955078125
..but it fails pretty badly once it comes to looking at objects outside of your local zone:
from tzlocal import get_localzone
from pytz import utc
utc_now = datetime.now(tz=localzone).astimezone(utc)
dt_to_timestamp(utc_now) - time.time()
# 21599.98956131935, more commonly known as 21600 -- my offset from UTC
This is what I finally ended up with:
from datetime import datetime
from pytz import utc
def dt_to_timestamp(dt_object):
"""Provides timestamp for any zone-aware datetime object.
Works with Python 2.7 and Python 3.3, possibly others.
Raises TypeError when naive datetime objects are given.
"""
epoch = datetime(1970, 1, 1, tzinfo=utc)
delta = dt_object - epoch
return delta.total_seconds()
# example usage:
from tzlocal import get_localzone
ts = 1382832000
utc_dt = utc.localize(datetime.utcfromtimestamp(ts))
local_dt = utc_dt.astimezone(get_localzone())
ts == dt_to_timestamp(utc_dt) == dt_to_timestamp(local_dt)
# True
It handles aware datetime objects accurately, whatever their timezone. If the caller doesn't know the timezone in order to turn it into an aware timezone, then there are other problems. :-) I'm of the opinion that one should always use an aware datetime objects if possible, and when not using aware datetime objects, use UTC datetimes.
I found the info for this answer (amongst a lot of other detail) here.

Categories