using unix timestamp generate timedelta for babel's format_timedelta - python

I am not sure I worded that correctly but python and time always confuses me.
This is what I am trying.
Given a unix timestamp (INT) which is definitely in the past (can be seconds ago or years ago) I want to generate a babel format_timedelta
My problem is
Babel format_timedelta takes timedelta as first argument
so I guess I need to generate a timedelta using time.time() (now) and the unix timestamp I have.
I can't figure out the part 2 and I believe there must be an easier/correct way to do this. Please share the best possible way to do this, also I need it to be fast in calculating since I have to use it in a web page.
def format_starttime(value, granularity="day"):
delta = datetime.timedelta(seconds=time.time() - value)
return format_timedelta(delta, granularity)
gives error in date.format_timedelta()
AttributeError: 'module' object has no attribute 'format_timedelta'

import datetime
td = datetime.timedelta(seconds=time.time()-a_unix_timestamp)

Difference between two datetime instances is a timedelta instance.
from datetime import datetime
from babel.dates import format_timedelta
delta = datetime.now() - datetime.fromtimestamp(your_timestamp)
print format_timedelta(delta, locale='en_US')
See datetime module documentation for details and more examples.

Related

How do I get the full timezone name from a Datetime without importing Time?

I'm trying to display my full time zone along with my current local time.
print "Your current time is {0} {1} ".format(datetime.datetime.now().time(), time.tzname[0])
And the result would look something like:
Your current time is 08:35:45.328000 Pacific Standard Time
The problem is I have to import the Time library (sorry if I call it wrong, I'm coming from C#) along with the Datetime library.
import datetime
import time
I've looked into the naive and aware states of time, but still can't seem to get the desired result.
Is there a way to get the full timezone name (i.e.: Pacific Standard Time) from Datetime without having to import Time?
The example for writing your own local timezone tzinfo class uses (scroll down one page from here) pulls the tzname from time.tzname, so Python doesn't have a better built-in solution to suggest.
You could copy that example LocalTimezone implementation, which would allow the use of the %Z format code for strftime on an aware datetime instance using the LocalTimezone, but that's the best you can do with the built-ins. On a naive datetime the tzname is the empty string, so you need an aware datetime for this to work.

How should I serialize a dateutil.tz.tzlocal object?

I want to capture a timestamp and the current timezone and serialize it into a file (in JSON or YAML, but that's not really my question) for later retrieval on a different computer.
The timestamp is easy, I'll just use time.time().
For getting the current timezone, I read another SO question and it seems appropriate to use dateutil.tz.tzlocal
to get the current timezone.
Now I just need to figure out how to serialize it. The name is easy, that's just a string, but the offset seems to be weird; I was expecting just a number:
import time
import datetime
import dateutil
now = datetime.datetime.utcfromtimestamp(time.time())
tzlocal = dateutil.tz.tzlocal()
print tzlocal.tzname(now)
print tzlocal.utcoffset(now)
but this prints
US Mountain Standard Time
-1 day, 17:00:00
and the result of utcoffset appears to be an object. How do I just get the number?
Oh, never mind, tzlocal.utcoffset(now) returns a datetime.timedelta and I can just call total_seconds():
import time
import datetime
import dateutil
import json
now = datetime.datetime.utcfromtimestamp(time.time())
tzlocal = dateutil.tz.tzlocal()
info_str = json.dumps(dict(name=tzlocal.tzname(now),
offset=tzlocal.utcoffset(now).total_seconds()))
print info_str
which prints (on my PC)
{"name": "US Mountain Standard Time", "offset": -25200.0}
I'm not sure what your application is but as a default I recommend serializing to ISO 8601 timestamps with a time zone offset. Even better, convert to UTC first... this makes things easier for humans who happen to browse the serialized data, because they don't have to do the date math in their head.
There may be performance reasons for sticking with numeric timestamps, but I'd want proof this was a bottleneck in my application before giving up the human-readable bonus of ISO timestamps.

Python2 datetime - Convert epoch time to UTC timestamp with offset

I am using Python 2 due to reasons beyond my control and hence cannot upgrade to Python 3 (which has better support for timezones).
I have an epoch time like 1492464960.53 and I want to convert it into a timestamp like this 2017-04-17T21:36:00.530000+00:00.
I tried using the following code but this does not give the +00:00 part of the timestamp that I also need.
import datetime
created=1492464960.53
time_str = datetime.datetime.utcfromtimestamp(created).isoformat()
print(time_str)
>> 2017-04-17T21:36:00.530000
How can I add the +00:00 part?
Just tried this out and it worked for me.
First to explain why original solution didn't work, from what I understand, the reason isoformat() will not work for above epoch value is because this method requires the object to return something with the 'utcoffset' attribute, however above float/epoch value returns 'None' when I tested it out with this attribute.
The isoformat method may very well work if we weren't dealing with converting a float perhaps.
Anyways, onto the solution:
from datetime import datetime, tzinfo
import pytz
created = 1492464960.53
dt = datetime.utcfromtimestamp(created)
##print results for above 'dt' variable
2017-04-17 21:36:00.530000
dt = dt.replace(tzinfo=pytz.utc)
##print results for above 'dt' variable
2017-04-17 21:36:00.530000+00:00
dt.isoformat()
##print results for above 'dt' variable
'2017-04-17T21:36:00.530000+00:00'
Sorry, not sure what you mean exactly about installing pytz, I just pip installed pytz then added the import statement in my python shell on my local machine.
Not sure this is the best solution, however it seems to have worked so here is the alternative I can offer:
created = 1492464960.53
dt = dt.utcnow().fromtimestamp(created, dt.tzname()).isoformat()
should print
'2017-04-17T14:36:00.530000'
from datetime import time
t = time(00, 00, 00, tzinfo=dt.tzname())
tmstmp = dt.isoformat()+'+'+t.strftime("%M:%S %z")
should print
2017-04-17T21:36:00.530000+00:00

Get timestamp in seconds from python's datetime

How to get timestamp from the structure datetime? What is right alternative for non-existing datetime.utcnow().timestamp()?
use time, and int to remove the milliseconds
from time import time
int(time())
# 1561043225
import time,datetime
time.mktime(datetime.datetime.today().timetuple())
If you don't have to get timestamp from structure datetime, you can decrease instruction like this
import time
print time.time()
There is another stupid trick - achieve timedelta
(datetime.utcnow()-datetime(1970,1,1,0,0,0)).total_seconds()
found here. Better
(datetime.utcnow()-datetime.fromtimestamp(0)).total_seconds()
And this solution contains subseconds.
If I understand correctly what sort of output you are seeking:
from datetime import datetime
timestamp = datetime.now().strftime("%H:%M:%S")
print(timestamp)
> 11:44:40
EDIT: Appears I misinterpreted your question? You are asking for the naive universal time, then galaxyan's answer is concise.

Elegant way to adjust date timezones in Python

I'm based in the UK, and grappling with summer time BST and timezones.
Here's my code:
TIME_OFFSET = 1 # 0 for GMT, 1 for BST
def RFC3339_to_localHHMM(input):
# Take an XML date (2013-04-08T22:35:00Z)
# return e.g. 08/04 23:35
return (datetime.datetime.strptime(input, '%Y-%m-%dT%H:%M:%SZ') +
datetime.timedelta(hours=TIME_OFFSET)).strftime('%d/%m %H:%M')
Setting a variable like this feels very wrong, but I can't find any elegant way to achieve the above without hideous amounts of code. Am I missing something, and is there no way to (for example) read the system timezone?
To convert UTC to given timezone:
from datetime import datetime
import pytz
local_tz = pytz.timezone("Europe/London") # time zone name from Olson database
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)
rfc3339s = "2013-04-08T22:35:00Z"
utc_dt = datetime.strptime(rfc3339s, '%Y-%m-%dT%H:%M:%SZ')
local_dt = utc_to_local(utc_dt)
print(local_dt.strftime('%d/%m %H:%M')) # -> 08/04 23:35
See also How to convert a python utc datetime to a local datetime using only python standard library?.
You seem to be asking a few separate questions here.
First, if you only care about your own machine's current local timezone, you don't need to know what it is. Just use the local-to-UTC functions. There are a few holes in the API, but even if you can't find the function you need, you can always just get from local to UTC or vice-versa by going through the POSIX timestamp and the fromtimestamp and utcfromtimestamp methods.
If you want to be able to deal with any timezone, see the top of the docs for the difference between aware and naive objects, but basically: an aware object is one that knows its timezone. So, that's what you need. The problem is that, as the docs say:
Note that no concrete tzinfo classes are supplied by the datetime module. Supporting timezones at whatever level of detail is required is up to the application.
The easiest way to support timezones is to install and use the third-party library pytz.
Meanwhile, as strftime() and strptime() Behavior sort-of explains, strptime always returns a naive object. You then have to call replace and/or astimezone (depending on whether the string was a UTC time or a local time) to get an aware object imbued with the right timezone.
But, even with all this, you still need to know what local timezone you're in, which means you still need a constant. In other words:
TIMEZONE = pytz.timezone('Europe/London')
def RFC3339_to_localHHMM(input):
# Take an XML date (2013-04-08T22:35:00Z)
# return e.g. 08/04 23:35
utc_naive = datetime.datetime.strptime(input, '%Y-%m-%dT%H:%M:%SZ')
utc = utc_naive.replace(pytz.utc)
bst = utc.astimezone(TIMEZONE)
return bst.strftime('%d/%m %H:%M')
So, how do you get the OS to give you the local timezone? Well, that's different for different platforms, and Python has nothing built in to help. But there are a few different third-party libraries that do, such as dateutil. For example:
def RFC3339_to_localHHMM(input):
# Take an XML date (2013-04-08T22:35:00Z)
# return e.g. 08/04 23:35
utc = datetime.datetime.strptime(input, '%Y-%m-%dT%H:%M:%SZ')
bst = utc.astimezone(dateutil.tz.tzlocal())
return bst.strftime('%d/%m %H:%M')
But now we've come full circle. If all you wanted was the local timezone, you didn't really need the timezone at all (at least for your simple use case). So, this is only necessary if you need to support any timezone, and also want to be able to, e.g., default to your local timezone (without having to write two copies of all of your code for the aware and naive cases).
(Also, if you're going to use dateutil in the first place, you might want to use it for more than just getting the timezone—it can basically replacing everything you're doing with both datetime and pytz.)
Of course there are other options besides these libraries—search PyPI, Google, and/or the ActiveState recipes.
If you want to convert a UTC input into a local time, regardless of which timezone you're in, try this:
def utctolocal(input):
if time.localtime()[-1] == 1: st=3600
else: st=0
return time.localtime(time.time()-time.mktime(time.gmtime())+time.mktime(time.localtime(time.mktime(time.strptime(input, '%Y-%m-%dT%H:%M:%SZ'))))+st)
Quite long code, but what it does is it simply adds the difference between time.gmtime() and time.localtime() to the time tuple created from the input.
Here's a function I use to do what I think you want. This assumes that the input is really a gmt, or more precisely, a utc datetime object:
def utc_to_local(utc_dt):
'''Converts a utc datetime obj to local datetime obj.'''
t = utc_dt.timetuple()
secs = calendar.timegm(t)
loc = time.localtime(secs)
return datetime.datetime.fromtimestamp(time.mktime(loc))
Like you said, this relies on the system time zone, which may give you shaky results, as some of the comments have pointed out. It has worked perfectly for me on Windows, however.
A simple function to check if a UCT corresponds to BST in London or GMT (for setting TIME_OFFSET above)
import datetime
def is_BST(input_date):
if input_date.month in range(4,9):
return True
if input_date.month in [11,12,1,2]:
return False
# Find start and end dates for current year
current_year = input_date.year
for day in range(25,32):
if datetime.datetime(current_year,3,day).weekday()==6:
BST_start = datetime.datetime(current_year,3,day,1)
if datetime.datetime(current_year,10,day).weekday()==6:
BST_end = datetime.datetime(current_year,10,day,1)
if (input_date > BST_start) and (input_date < BST_end):
return True
return False

Categories