Python Convert time to UTC format - python

from django.utils import timezone
time_zone = timezone.get_current_timezone_name() # Gives 'Asia/Kolkata'
date_time = datetime.time(12,30,tzinfo=pytz.timezone(str(time_zone)))
Now I need to convert this time to UTC format and save it in Django model. I am not able to use date_time.astimezone(pytz.timezone('UTC')). How can I convert the time to UTC. Also Back to 'time_zone'.
This is a use case when user type time in a text box and we need to save time time in UTC format. Each user will also select his own time zone that we provide from Django timezone module.
Once the user request back the saved time it must be shown back to him in his selected time zone.

These things are always easier using complete datetime objects, e.g.:
import datetime
import pytz
time_zone = pytz.timezone('Asia/Kolkata')
# get naive date
date = datetime.datetime.now().date()
# get naive time
time = datetime.time(12, 30)
# combite to datetime
date_time = datetime.datetime.combine(date, time)
# make time zone aware
date_time = time_zone.localize(date_time)
# convert to UTC
utc_date_time = date_time.astimezone(pytz.utc)
# get time
utc_time = utc_date_time.time()
print(date_time)
print(utc_date_time)
print(utc_time)
Yields:
2014-07-13 12:30:00+05:30
2014-07-13 07:00:00+00:00
07:00:00
right now for me.

set the timezone to UTC in your settings.py. Get the user input of time and timezone in certain format. Suppose you get the user time as 'Jul-7-2014 12:35PM:30' (consider using date input in your html).
from datetime import datetime, timedelta
// convert the time to standard format
user_date = datetime.strptime('Jul-7-2014 12:35PM:30', '%b-%d-%Y %I:%M%p:%S')
user_date_string = user_date.strftime('%Y-%m-%d %H:%M:%S')
// save the time to model with users timezone
// now when user asks back for his time, add the timezone with timedelta
user_date = datetime.strptime(user_date_string, '%Y-%m-%d %H:%M:%S')
user_date = user_date + timedelta(hours = 5, minutes = 30)
// finally display it
print user_data.strftime('%Y-%m-%d %H:%M:%S')
*this is not considering django inbuild datetime functions which returns datetime object for datetime model field. If implemented that it will be more simple

Related

How to convert string datetime to UTC UNIX?

I have date in the as string in the following format: 202001010000
I am trying to convert this to UNIX format and get the result in UTC
I did:
import datetime
stime = "202001010000"
print(int(datetime.datetime.strptime(stime, "%Y%m%d%H%M").replace(tzinfo=datetime.timezone.utc).timestamp()))
and this is giving me the output in UNIX, but in CEST format.
With the above code I get: 1577836800 but I want the output to be 1577833200
What is the mistake I am doing?
You're setting time zone to UTC when converting to datetime. But since your input represents time in Germany you want a time zone that is active there. EX:
from datetime import datetime
from zoneinfo import ZoneInfo # Python 3.9+, can use backports.zoneinfo for older versions
stime = "202001010000"
# stime represents time in Germany so we use time zone
time_zone = ZoneInfo('Europe/Berlin')
# to datetime, with tz set:
dtobj = datetime.strptime(stime, "%Y%m%d%H%M").replace(tzinfo=time_zone)
# unix time
ts = dtobj.timestamp()
print(ts)
# 1577833200.0
# back to datetime, again specify time zone
dtobj = datetime.fromtimestamp(ts, tz=time_zone)
print(dtobj)
# 2020-01-01 00:00:00+01:00
Note that if the input represents the same time zone your OS is configured to use, this works correctly without setting a time zone. But I think it's better to be explicit here, to avoid confusion if you e.g. run this script on a machine configured to use another time zone.
What you're trying to get is 7 hours behind and you cannot do that from your start date. You must push your start date back 1 day and push your hours forward 17. This code will work for you
import datetime
stime = "201912310000"
my_date = datetime.datetime.strptime(stime, "%Y%m%d%H%M")
my_date_utc = my_date.replace(hour=17)
my_timestamp = my_date_utc.timestamp()
print(int(my_timestamp))

How to format a date value for Hubspot API using Python

I have read the docs saying that to pass the value for a Hubspot date field you should format your Date as midnight UTC. However, I've had no luck doing so in Python. I assume I am just missing the magic Python incantation that will get the right result. Here is what I have:
from pytz import timezone, utc
from hubspot.crm.contacts import SimplePublicObject,
created_dt = # datetime from sqlalchemy query
utcdt = utc.localize(
datetime(
year=created_dt.year,
month=created_dt.month,
day=created_dt.day
)
)
ts = int(utcdt.timestamp())
props = SimplePublicObjectInput({"last_booking": str(ts)})
return client.crm.companies.basic_api.update(
hs_id, simple_public_object_input=props
)
this returns this error:
{"status":"error",
"message":"Property values were not valid: [{\"isValid\":false,\"message\":\"1570233600 is at 4:10:33.600 UTC, not midnight!\"...
}
Ah, the answer was right there. Python timestamp returns the time in seconds, and HubSpot expects milliseconds. I just had to multiply by 1000:
ts = int(utcdt.timestamp()*1000)
now all looks good.
did you try adding hours and minutes to your datetime call
datetime(
year=created_dt.year,
month=created_dt.month,
day=created_dt.day,
hour=0,
minute=0
)
Use the Hubspot supported "sanetime" module: https://github.com/HubSpot/sanetime
Then to get a date:
yourdate = datetime.datetime.date()
hubspot_date = sanetime.time(yourdate )
Or if you do not want a dependency:
#convert datetime to UTC
your_utc_datetime = your_datetime.astimezone(pytz.UTC)
#replace time with midnight
your_utc_date_midnight = your_utc_datetime.replace(hour=0,minute=0,second=0, microsecond=0)
# convert to epoch (Python 3.3+)
your_hubspot_date = your_utc_date_midnight.timestamp()*1000

Python string to Django timezone (aware datetime)

TL;DR;
How to convert 2016-01-01 to Django timezone?
Full version:
I receive a query string parameter from a form and I wanna get that string and use it as a datetime filter in Django.
The problem is that when I convert the string to a datetime, it's not making an aware datetime and so I lose a few hours due to timezone different. Maybe I'm losing myself in the formatting, but I'm not being able to do it.
I have pytz, I have USE_TZ = True in my settings as well.
example:
from datetime import date
# Example from what I receive as GET querystring parameter
start_date, end_date = '15-01-2016', '16-01-2016'
DATE_FORMAT = '%Y-%m-%d'
start_date = start_date.split('-')
start_date = date(int(start_date[2]), int(start_date[1]), int(start_date[0]))
sd_filter = start_date.strftime(DATE_FORMAT)
end_date = end_date.split('-')
end_date = date(int(end_date[2]), int(end_date[1]), int(end_date[0]))
ed_filter = end_date.strftime(DATE_FORMAT)
#query
my_list = MyModel.objects.filter(created_at__range=(sd_filter, ed_filter))
the problem lies in the filter. I'm losing a few hours due to timezone from Django settings.
UPDATE: I don't need to convert a datetime.now() to my time. I need to convert a string to datetime.
I know this is old but maybe will be helpful since I got into this situation as well:
What about using make_aware() ?
from datetime import datetime
from django.utils.timezone import make_aware
date = '22-05-2018'
aware = make_aware(datetime.strptime(date, '%d-%m-%Y'))
This will use the currently active timezone (activated by timezone.activate). If no timezone is activated explicitly, it would use the default timezone -- TIME_ZONE specified in settings.py.
You are comparing time-zone unaware Python Date objects with the time-zone aware DateTimeField fields in your database. It is probably more intuitive to use DateTime objects - and these can be made time-zone aware easily as follows:
import datetime
import pytz
start_date = '15-01-2016'
end_date = '16-01-2016'
date_format = '%d-%m-%Y'
unaware_start_date = datetime.datetime.strptime(start_date, date_format)
aware_start_date = pytz.utc.localize(unaware_start_date)
unaware_end_date = datetime.datetime.strptime(end_date, date_format)
aware_end_date = pytz.utc.localize(unaware_end_date)
my_list = MyModel.objects.filter(created_at__range=(aware_start_date, aware_end_date))
This creates unaware_start_date and unaware_end_date DateTime objects using strptime(). It then uses pytz.utc.localize to make the objects time-zone aware (you will need to replace utc with your relevant time-zone).
You can then have time-zone aware DateTime objects - aware_start_date and aware_end_date. Feeding these into your filter should yield the desired results.
from django.utils import timezone
timestamp_raw = timezone.now() #current time, or use whatever time you have
date_format = '%Y-%m-%d %H:%M:%S' #time format day-month-year hour:minutes:seconds
timestamp = timezone.datetime.strftime(timestamp_raw, date_format)
Or Using the new f-string formatter
f"{timezone:%Y-%m-%d %H:%M:%S %p}"

Check if the date of a timezone is passed current time

I receive time in the format 12:00 and I also have a timezone in the format <DstTzInfo 'Europe/Paris' PMT+0:09:00 STD>. I want to see, if this date is already passed current time in that timezone.
My current timezone may be different from the timezone I receive, so I use the following:
tz = pytz.timezone('Europe/Paris')
d = parse("14:39").replace(tzinfo=tz)
now = datetime.datetime.now(tz)
print (d - now).total_seconds()
Even though the current time in Paris is 14:39, I still get 6600 seconds. I also tried now = datetime.datetime.replace(tzinfo=tz), but I get -3600 seconds.
What I want is having time in a specified timezone, check whether it passed or not.
What about this:
from datetime import datetime
from dateutil import tz
tz = tz.gettz('Europe/Paris')
now = datetime.now().replace(tzinfo=tz)
d = datetime.strptime("{0}/{1}/{2} 14:39".format(now.year,now.month,now.day), "%Y/%m/%d %H:%M").replace(tzinfo=tz)
print (d-now).total_seconds()
I keep the current time in now, in the Europe/Paris timezone, and also create d in the same timezone. If their difference is negative the date is already passed current time in that timezone.

Converting datetime to POSIX time

How do I convert a datetime or date object into a POSIX timestamp in python? There are methods to create a datetime object out of a timestamp, but I don't seem to find any obvious ways to do the operation the opposite way.
import time, datetime
d = datetime.datetime.now()
print time.mktime(d.timetuple())
For UTC calculations, calendar.timegm is the inverse of time.gmtime.
import calendar, datetime
d = datetime.datetime.utcnow()
print calendar.timegm(d.timetuple())
Note that Python now (3.5.2) includes a built-in method for this in datetime objects:
>>> import datetime
>>> now = datetime.datetime(2020, 11, 18, 18, 52, 47, 874766)
>>> now.timestamp() # Local time
1605743567.874766
>>> now.replace(tzinfo=datetime.timezone.utc).timestamp() # UTC
1605725567.874766 # 5 hours delta (I'm in UTC-5)
In python, time.time() can return seconds as a floating point number that includes a decimal component with the microseconds. In order to convert a datetime back to this representation, you have to add the microseconds component because the direct timetuple doesn't include it.
import time, datetime
posix_now = time.time()
d = datetime.datetime.fromtimestamp(posix_now)
no_microseconds_time = time.mktime(d.timetuple())
has_microseconds_time = time.mktime(d.timetuple()) + d.microsecond * 0.000001
print posix_now
print no_microseconds_time
print has_microseconds_time
Best conversion from posix/epoch to datetime timestamp and the reverse:
this_time = datetime.datetime.utcnow() # datetime.datetime type
epoch_time = this_time.timestamp() # posix time or epoch time
this_time = datetime.datetime.fromtimestamp(epoch_time)
It depends
Is your datetime object timezone aware or naive?
Timezone Aware
If it is aware it's simple
from datetime import datetime, timezone
aware_date = datetime.now(tz=timezone.utc)
posix_timestamp = aware_date.timestamp()
as date.timestamp() gives you "POSIX timestamp"
NOTE: more accurate to call it an epoch/unix timestamp as it may not be POSIX compliant
Timezone Naive
If it's not timezone aware (naive), then you'd need to know what timezone it was originally in so we can use replace() to convert it into a timezone aware date object. Let's assume that you've stored/retrieved it as UTC Naive. Here we create one, as an example:
from datetime import datetime, timezone
naive_date = datetime.utcnow() # this date is naive, but is UTC based
aware_date = naive_date.replace(tzinfo=timezone.utc) # this date is no longer naive
# now we do as we did with the last one
posix_timestamp = aware_date.timestamp()
It's always better to get to a timezone aware date as soon as you can to prevent issues that can arise with naive dates (as Python will often assume they are local times and can mess you up)
NOTE: also be careful with your understanding of the epoch as it is platform dependent

Categories

Resources