A specific bank has branches in all major cities in the world. They all open at 10:00 AM local time. If within a timezone that uses DST, then of course the local opening time also follows the DST-adjusted time. So how do I go from the local time to the utc time.
What I need is a function to_utc(localdt, tz) like this:
Arguments:
localdt: localtime, as naive datetime object, DST-adjusted
tz: timezone in the TZ-format, e.g. 'Europe/Berlin'
Returns:
datetime object, in UTC, timezone-aware
EDIT:
The biggest challenge is to detect whether the local time is in a period with DST, which also means that it is DST adjusted.
For 'Europe/Berlin' which has +1 DST in the summer:
Jan 1st 10:00 => Jan 1st 9:00 UTC
July 1st 10:00 => July 1st 8:00 UTC
For 'Africa/Lagos' which has no DST:
Jan 1st 10:00 => Jan 1st 9:00 UTC
July 1st 10:00 => July 1st 9:00 UTC
Using pytz, and in particular its localize method:
import pytz
import datetime as dt
def to_utc(localdt,tz):
timezone=pytz.timezone(tz)
utc=pytz.utc
return timezone.localize(localdt).astimezone(utc)
if __name__=='__main__':
for tz in ('Europe/Berlin','Africa/Lagos'):
for date in (dt.datetime(2011,1,1,10,0,0),
dt.datetime(2011,7,1,10,0,0),
):
print('{tz:15} {l} --> {u}'.format(
tz=tz,
l=date.strftime('%b %d %H:%M'),
u=to_utc(date,tz).strftime('%b %d %H:%M %Z')))
yields
Europe/Berlin Jan 01 10:00 --> Jan 01 09:00 UTC
Europe/Berlin Jul 01 10:00 --> Jul 01 08:00 UTC
Africa/Lagos Jan 01 10:00 --> Jan 01 09:00 UTC
Africa/Lagos Jul 01 10:00 --> Jul 01 09:00 UTC
from datetime import datetime, tzinfo, timedelta
class GMT1(tzinfo):
def utcoffset(self, dt):
return timedelta(hours=1)
def dst(self, dt):
return timedelta(0)
def tzname(self,dt):
return "Europe/Prague"
year, month, day = 2011, 7, 23
dt = datetime(year, month, day, 10)
class UTC(tzinfo):
def utcoffset(self, dt):
return timedelta(0)
def dst(self, dt):
return timedelta(0)
def tzname(self,dt):
return "UTC"
def utc(localt, tz):
return localt.replace(tzinfo=tz).astimezone(UTC())
print utc(dt, GMT1())
New Version. This does what you want -- takes a naive datetime and a timezone and returns a UTC datetime.
Related
I am having issues converting a datetime string of this format "%d %b %Y %X %Z" to "%Y-%m-%dT%X%z". The timezone information is stripped out. For example:
>> import datetime
>> datetime_string_raw = "18 Nov 2022 08:57:04 EST"
>> datetime_utc = datetime.datetime.strptime(datetime_string_raw, "%d %b %Y %X %Z").strftime("%Y-%m-%dT%X%z")
>> print(datetime_utc)
2022-11-18T08:57:04
How can I get it to print the UTC offset? Why doesn't the %Z and %z have any effect? Thanks!
Using dateutil's parser and a definition which abbreviated names should resemble which time zone:
import datetime
import dateutil # pip install python-dateutil
tzinfos = {"EST": dateutil.tz.gettz("America/New_York"),
"EDT": dateutil.tz.gettz("America/New_York")}
datetime_string_raw = "18 Nov 2022 08:57:04 EST"
datetime_ny = dateutil.parser.parse(datetime_string_raw, tzinfos=tzinfos)
print(datetime_ny)
# 2022-11-18 08:57:04-05:00
datetime_utc = datetime_ny.astimezone(datetime.timezone.utc)
print(datetime_utc)
# 2022-11-18 13:57:04+00:00
You can do basically the same using only the standard library, but it requires some pre-processing of the date/time string. Ex:
import datetime
import zoneinfo # Python >= 3.9
def parse_dt_with_tz(dt_string: str, fmt: str, tzinfos: dict) -> datetime.datetime:
"""Parse date/time string with abbreviated time zone name to aware datetime."""
parts = dt_string.split(" ")
tz = tzinfos.get(parts[-1]) # last element is the tz name
if not tz:
raise ValueError(f"no entry found for {parts[-1]} in tzinfos")
return datetime.datetime.strptime(" ".join(parts[:-1]), fmt).replace(tzinfo=tz)
# usage
tzinfos = {"EST": zoneinfo.ZoneInfo("America/New_York"),
"EDT": zoneinfo.ZoneInfo("America/New_York")}
s = "18 Nov 2022 08:57:04 EST"
dt = parse_dt_with_tz(s, "%d %b %Y %H:%M:%S", tzinfos)
print(dt, repr(dt))
# 2022-11-18 08:57:04-05:00 datetime.datetime(2022, 11, 18, 8, 57, 4, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
I'm trying to convert UTC time to Europe/Warsaw time. Warsaw time is now UTC + 2 hours. I don't know why I get result with time 30 minutes eariler. I'm parsing date from string similar to: 7:27:02 AM or 2:16:28 PM.
print(time_str) #6:47:46 PM
format = '%I:%M:%S %p'
time_obj = datetime.strptime(time_str, format)
utc_time = time_obj.replace(tzinfo=ZoneInfo('Etc/UTC'))
converted_time = utc_time.astimezone(tz=ZoneInfo('Europe/Warsaw')).time()
print(utc_time.time(), converted_time)
Output is
6:47:46 PM
18:47:46
20:11:46
While I expect:
6:47:46 PM
18:47:46
20:47:46
EDIT - this line fixed it:
time_obj = datetime.strptime(time_str, format).replace(year=2021, month=7, day=14)
I am trying to run a python cron script that will batch convert all video files inside a directory.
The python script is based on MoviePy and is working seamlessly when triggered manually.
But when triggered in Cron Job, its not running/working as estimated.
I have set a Shell Script inside which i have kept the Python script for any error crash handling.
I am calling the shell script from the cron.
Here are my codes:
Crontab -e:
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
# * * * * * /usr/bin/python3 /var/www/html/cgi-bin/in.py /var/www/html/cgi-bin/log.txt
# * * * * * /bin/bash -c "/var/www/html/cgi-bin/cron.sh"
* * * * * cd /bin/bash /var/www/html/cgi-bin/cron.sh > /var/www/html/cgi-bin/log.txt 2> &1
Cron.sh is my Shell File that Cron will run.
#!/bin/sh
echo $(date) >> /var/www/html/cgi-bin/log.txt
/usr/bin/python3 /var/www/html/cgi-bin/in.py >> /var/www/html/cgi-bin/log.txt
Here is my Python File - In.py :
import moviepy.editor as mp
import sys, getopt
import requests
from datetime import datetime
from random import randint
import os, os.path, random
import shutil
rand_aud = str(randint(0, len(os.listdir('aud/'))))
inputfile = ''
keypass = ''
def main(argv):
inputfile = ''
keypass = ''
try:
opts, args = getopt.getopt(argv,"hi:k:",["ifile=","key="])
except getopt.GetoptError:
print ('in.py -i <inputfile> -k <user_key>')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print ('in.py -i <inputfile> -k <user_key>')
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-k", "--key"):
keypass = arg
# print(inputfile)
# print(keypass)
directory = r'in/'
for filename in os.listdir(directory):
inp = os.path.join(directory, filename)
#if inp == '':
# inp = 'in/f.mp4'
now = datetime.now()
value = randint(0, 10)
dt_stamp = now.strftime("%d%m%Y%H%M%S") + str(value)
out = 'out/' + keypass + '_' + dt_stamp + '.webm'
# aud = 'aud/' + rand_aud +'.WAV'
aud = 'aud/' + random.choice(os.listdir("aud/"))
print(out)
logu = 'logo.png'
video = mp.VideoFileClip(inp)
# if video.rotation == 90:
video = video.resize(video.size[::-1])
video.rotation = 0
logo = (mp.ImageClip(logu)
.set_duration(video.duration)
.resize(height=50) # if you need to resize...
.margin(right=8, top=8, opacity=0) # (optional) logo-border padding
.set_pos(("right","top")))
if aud != '':
audioclip = mp.AudioFileClip(aud).set_duration(video.duration)
new_audioclip = mp.CompositeAudioClip([audioclip])
video.audio = new_audioclip
final = mp.CompositeVideoClip([video, logo])
final.write_videofile(out)
if os.path.exists(inp):
os.remove(inp)
url = 'https://get-data.worlds.com.au?Auth=SSSOSXSQSSSXSQSXSOSSSOSS&Sender_key=' + keypass + '&handle=stream_response'
# print ('Posting Data To ' + url)
userdata = {"loc": out, "stamp": dt_stamp, "Auth": keypass, "handle": "stream"}
resp = requests.post(url)
# files = {'file': open(out, 'rb')}
# userdata = {"loc": out, "stamp": dt_stamp, "Auth": keypass, "handle": "stream"}
# resp = requests.post(url, files=files, params=userdata)
# r = requests.get(url, headers={"Auth":keypass, "handle":"stream"})
# print ('Call Response:')
# print (resp)
if __name__ == "__main__":
main(sys.argv[1:])
Here is the log.txt file. Please note that the MoviePy Done was the one i performed manually. Rest are CRON calls. The ones that have only time in them shows the cron job is running but the python script isnt :
Mon Apr 12 08:38:17 UTC 2021
out/_120420210838183.webm
Moviepy - Building video out/_120420210838183.webm.
MoviePy - Writing audio in _120420210838183TEMP_MPY_wvf_snd.ogg
MoviePy - Done.
Moviepy - Writing video out/_120420210838183.webm
Moviepy - Done !
Moviepy - video ready out/_120420210838183.webm
out/_120420210838374.webm
Moviepy - Building video out/_120420210838374.webm.
MoviePy - Writing audio in _120420210838374TEMP_MPY_wvf_snd.ogg
MoviePy - Done.
Moviepy - Writing video out/_120420210838374.webm
Moviepy - Done !
Moviepy - video ready out/_120420210838374.webm
Mon Apr 12 08:39:01 UTC 2021
Mon Apr 12 08:40:01 UTC 2021
Mon Apr 12 08:41:01 UTC 2021
Mon Apr 12 08:42:01 UTC 2021
Mon Apr 12 08:43:01 UTC 2021
Mon Apr 12 08:44:01 UTC 2021
Mon Apr 12 08:45:01 UTC 2021
Mon Apr 12 08:46:01 UTC 2021
Mon Apr 12 08:47:01 UTC 2021
Mon Apr 12 08:48:02 UTC 2021
Mon Apr 12 08:49:01 UTC 2021
Mon Apr 12 08:50:01 UTC 2021
Mon Apr 12 08:51:01 UTC 2021
Mon Apr 12 08:52:01 UTC 2021
Mon Apr 12 08:53:01 UTC 2021
Mon Apr 12 08:57:01 UTC 2021
Mon Apr 12 08:58:01 UTC 2021
Mon Apr 12 08:59:01 UTC 2021
Mon Apr 12 09:00:01 UTC 2021
Mon Apr 12 09:01:01 UTC 2021
Mon Apr 12 09:02:01 UTC 2021
Mon Apr 12 09:03:01 UTC 2021
Mon Apr 12 09:04:01 UTC 2021
Mon Apr 12 09:05:01 UTC 2021
Mon Apr 12 09:06:01 UTC 2021
Mon Apr 12 09:07:01 UTC 2021
Mon Apr 12 09:08:01 UTC 2021
Mon Apr 12 09:09:01 UTC 2021
Mon Apr 12 09:10:01 UTC 2021
Mon Apr 12 09:11:01 UTC 2021
Mon Apr 12 09:12:02 UTC 2021
Mon Apr 12 09:13:01 UTC 2021
Mon Apr 12 09:14:01 UTC 2021
Mon Apr 12 09:15:01 UTC 2021
Mon Apr 12 09:16:01 UTC 2021
Mon Apr 12 09:17:01 UTC 2021
I use this code to format my time but the time that comes out is 5 hours wrong. I should be 06 something in calcutta now and it formats the time now as 01... something. What is wrong with the code?
def datetimeformat_viewad(to_format, locale='en', timezoneinfo='Asia/Calcutta'):
tzinfo = timezone(timezoneinfo)
month = MONTHS[to_format.month - 1]
input = pytz.timezone(timezoneinfo).localize(
datetime(int(to_format.year), int(to_format.month), int(to_format.day), int(to_format.hour), int(to_format.minute)))
date_str = '{0} {1}'.format(input.day, _(month))
time_str = format_time(input, 'H:mm', tzinfo=tzinfo, locale=locale)
return "{0} {1}".format(date_str, time_str)
Update
This code worked which was according to the answer below.
def datetimeformat_viewad(to_format, locale='en', timezoneinfo='Asia/Calcutta'):
import datetime as DT
import pytz
utc = pytz.utc
to_format = DT.datetime(int(to_format.year), int(to_format.month), int(to_format.day), int(to_format.hour), int(to_format.minute))
utc_date = utc.localize(to_format)
tzone = pytz.timezone(timezoneinfo)
tzone_date = utc_date.astimezone(tzone)
month = MONTHS[int(tzone_date.month) - 1]
time_str = format_time(tzone_date, 'H:mm')
date_str = '{0} {1}'.format(tzone_date.day, _(month))
return "{0} {1}".format(date_str, time_str)
It sounds like to_format is a naive datetime in UTC time.
You want to convert it to Calcutta time.
To do this, you localize to_format to UTC time1, and then use astimezone to convert that timezone-aware time to Calcutta time:
import datetime as DT
import pytz
utc = pytz.utc
to_format = DT.datetime(2015,7,17,1,0)
print(to_format)
# 2015-07-17 01:00:00
utc_date = utc.localize(to_format)
print(utc_date)
# 2015-07-17 01:00:00+00:00
timezoneinfo = 'Asia/Calcutta'
tzone = pytz.timezone(timezoneinfo)
tzone_date = utc_date.astimezone(tzone)
print(tzone_date)
# 2015-07-17 06:30:00+05:30
1The tzone.localize method does not convert between timezones. It
interprets the given localtime as one given in tzone. So if to_format is
meant to be interpreted as a UTC time, then use utc.localize to convert the
naive datetime to a timezone-aware UTC time.
I have the following format:
"Wed Jun 25 15:38:29 PDT 2014" and I would like to convert it to "2014-06-25 15:38:29", i.e. "%Y-%m-%d %H:%M:%S"
Code:
import time
import datetime
rawtime = "Wed Jun 25 15:38:29 PDT 2014"
dt = time.strptime(rawtime, "%Y-%m-%d %H:%M:%S")
print dt
I get the error:
ValueError: time data 'Wed Jun 25 15:38:29 PDT 2014\n' does not match format '%Y-%m-%d %H:%M:%S'
Simplest solution using dateutil package. It really is excellent at this.
from dateutil import parser
print parser.parse("Wed Jun 25 15:38:29 PDT 2014")
Output:
2014-06-25 15:38:29
First install pytz:
sudo easy_install --upgrade pytz
Then
import datetime
from pytz import timezone
rawtime = "Wed Jun 25 15:38:29 PDT 2014"
d = datetime.datetime.strptime(rawtime,'%a %b %d %H:%M:%S %Z %Y')
print(d.strftime("%Y-%m-%d %H:%M:%S"))
Should return:
2014-06-25 15:38:29
Just get rid of the PDT part:
import time
import datetime
rawtime = "Wed Jun 25 15:38:29 PDT 2014"
times = rawtime.split(' ')
del times[4]
dt = time.strptime(' '.join(times), '%a %b %d %H:%M:%S %Y')
print time.strftime("%Y-%m-%d %H:%M:%S", dt)
Should get you:
2014-06-25 15:38:29
pip install python-dateutil:
In [56]: from dateutil import parser
In [57]: parser.parse("Wed Jun 25 15:38:29 PDT 2014").strftime("%Y-%m-%d %H:%M:%S")
Out[57]: '2014-06-25 15:38:29'
Or manually:
In [58]: d = time.strptime("Wed Jun 25 15:38:29 PDT 2014","%a %b %d %H:%M:%S PDT %Y")
In [59]: "{}-{:02}-{:02} {:02}:{:02}:{:02}".format(d.tm_year,d.tm_mon,d.tm_mday,d.tm_hour,d.tm_min,d.tm_sec)
Out[59]: '2014-06-25 15:38:29'
Usually you need to call strptime or use dateutil to parse date strings. However in this case, rawtime looks similar enough to a date as specified by the RFC 2822 (Internet Message Format) that it can parsed using the standard library function email.utils.parsedate:
import email.utils as EU
import datetime as DT
rawtime = "Wed Jun 25 15:38:29 PDT 2014"
timetup = EU.parsedate(rawtime)
# (2014, 6, 25, 15, 38, 29, 0, 1, -1)
date = DT.datetime(*timetup[:6])
print(date)
# 2014-06-25 15:38:29
Hey So i found a solution for 95% of your problem.
import time
import datetime
rawtime = "Wed Jun 25 15:38:29 2014"
dt = time.strptime("%a %b %d %H:%M:%S %Y",rawtime)
print dt
this will out time.struct_time(tm_year=2014, tm_mon=6, tm_mday=25, tm_hour=15, tm_min=38, tm_sec=29, tm_wday=2, tm_yday=176, tm_isdst=-1)
After this you just need to create a string and place them in the right order you want. The only thing I wasn't sure of how to do off the top of my head was the PDT part of it.
To save the dt as a variable you can do
x = str(dt.tm_year) + "-" + str(dt.tm_mon) + "-" + str(dt.tm_mday) + " " + str(dt.tm_hour) + ":" + str(dt.tm_min) + ":" + str(dt.tm_sec)
print x
this will output 2014-6-25 15:38:29
Good luck!