Is there a way to find the local timezone with datetime? - python-3.x

I am trying to make some code that creates a clock using the user's local time with the datetime library.
import datetime as dt
import os
import time
z = dt.datetime.now()
def local_time():
def time_check(t):
if t < 10:
t = "0{}".format(t)
else:
t = t
return t
p = dt.datetime.now()
hour = p.hour
minute = p.minute
second = p.second
hour = time_check(hour)
minute = time_check(minute)
second = time_check(second)
local_time = '{}:{}:{}'.format(hour, minute, second)
return local_time
time_zone = z.timezone()
for i in range(999999999999999999999):
print("Time: {} {}".format(local_time(), time_zone))
time.sleep(1)
os.system("cls")
What I am doing is gathering the hour, minute, and second of the local time, and constantly updating it in the terminal, and deleting the previous time.
This works fine, but I am also trying to display the timezone of the user, and I am having a hard time trying to find a way to do it. Does anyone know a way? Thanks.

Importing the python-dateutil library should make this easier. Install the library with the pip install python-dateutil command at the terminal if you don't have it installed beforehand. Once you do that, test the below code:
from datetime import *
from dateutil.tz import *
print(datetime.now(tzlocal()).tzname())
print(datetime(2021, 6, 2, 16, 00, tzinfo=tzlocal()).tzname())
#Output
#SA Western Standard Time
#SA Western Standard Time
Using tzlocal() and tzname() together will give you the current timezone. The dateutil library is very powerful and useful. Check out the full documentation HERE.
Hopefully that helped.

Related

Python code works in IDE but when compiled in a .exe it doesn't work

I have written a basic program that takes the current internet time and adjusts the system time to be 2 mins ahead. The code can be seen below:
from datetime import timedelta
from datetime import datetime
import win32api
from urllib.request import urlopen
import admin
res = urlopen('http://just-the-time.appspot.com/')
result = res.read().strip()
now = result.decode('utf-8')
new_time = datetime.strptime(now, "%Y-%m-%d %H:%M:%S") + timedelta(hours=0, minutes=2, seconds=0)
year = new_time.year
month = new_time.month
day = new_time.day
hour = new_time.hour
minute = new_time.minute
second = new_time.second
win32api.SetSystemTime(year, month, 0, day, hour, minute, second,0)
print(new_time)
The program works perfectly when using the Pycharm IDE, however when I try to compile the code into an .exe using auto-py-to-exe or pyinstaller, the code runs but no changes are made to the system time. I have tried running as administrator but this doesn't seem to help. Can anyone help?

Python datetime parsing timestamp with timezone

I ran into this problem a while back ago where parsing an ISO string with time zone data and parsing a timestamp (supposedly of the same time) will give different results. I have written a test to check this behavior and it seems pretty inconsistent:
from pytz import timezone as tz
from datetime import datetime
timezone = "Australia/Sydney"
start_time = "2021-05-04T08:12:00"
tz_object = tz(timezone)
naive_datetime = datetime.fromisoformat(start_time)
zoned_time = datetime(naive_datetime.year, naive_datetime.month, naive_datetime.day, naive_datetime.hour, naive_datetime.minute, naive_datetime.second, tzinfo=tz_object)
parsed_time = datetime.fromtimestamp(zoned_time.timestamp(), tz_object)
assert zoned_time.time() == naive_datetime.time()
assert zoned_time.time() == parsed_time.time()
This test produces the following output
File "test.py", line 13, in <module>
assert zoned_time.time() == parsed_time.time()
AssertionError
Unless I'm missing something I can only conclude that the time resulting from this line
parsed_time = datetime.fromtimestamp(zoned_time.timestamp(), tz_object)
Is producing a different time than parsing the actual ISO string. Typically I'd expect the timestamp from the parsed time return a timestamp referring to 8:12 am in the time zone it was assigned.
Is this behavior expected?
Did I miss something?
With Python 3.9, use zoneinfo. Note that there is a deprecation shim for pytz if required.
Your code then works fine like
from datetime import datetime
from zoneinfo import ZoneInfo
timezone = "Australia/Sydney"
tz_object = ZoneInfo(timezone)
start_time = "2021-05-04T08:12:00"
naive_datetime = datetime.fromisoformat(start_time)
zoned_time = datetime(naive_datetime.year, naive_datetime.month, naive_datetime.day, naive_datetime.hour, naive_datetime.minute, naive_datetime.second, tzinfo=tz_object)
parsed_time = datetime.fromtimestamp(zoned_time.timestamp(), tz_object)
assert zoned_time.time() == naive_datetime.time()
assert zoned_time.time() == parsed_time.time()
As to why you got an assertion error: with pytz you need to localize the datetime object with the time zone; never set a tzinfo directly with pytz.

Refreshing boto3 session when paginating though cloudtrail

I'm writing a script in python using boto3 to report on the api calls made over the past few months. I have the script pretty much done but we have a max session length of 1 hour and this will always take longer than that and so the session expires and the script dies.
I have tried to refresh the session periodically to stop it from expiring but I cant't seem to make it work. I'm really hoping that someone has done this before and can tell me what I'm doing wrong?
Below is a cut down version of the code.
import boto3
import datetime
import time
from botocore.exceptions import ClientError
session_start_time = datetime.datetime.now()
start_date = datetime.datetime.now()
start_date -= datetime.timedelta(days=1)
end_date = datetime.datetime.now()
role='arn:aws:iam::1234:role/role'
def role_arn_to_session(**args):
client = boto3.client('sts')
response = client.assume_role(**args)
return boto3.Session(
aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken'])
session = role_arn_to_session(RoleArn=role,RoleSessionName='session')
cloudtrail = session.client('cloudtrail',region_name='us-east-1')
paginator = cloudtrail.get_paginator("lookup_events")
StartingToken = None
page_iterator = paginator.paginate(
PaginationConfig={'PageSize':1000, 'StartingToken':StartingToken },
StartTime=start_date,
EndTime=end_date)
for page in page_iterator:
for ct in page['Events']:
print(ct)
try:
token_file = open("token","w")
token_file.write(page["NextToken"])
StartingToken = page["NextToken"]
except KeyError:
break
if (datetime.datetime.now() - session_start_time).seconds/60 > 10:
page_iterator = None
paginator = None
cloudtrail = None
session = None
session = role_arn_to_session(RoleArn=role,RoleSessionName='session')
cloudtrail = session.client('cloudtrail',region_name='us-east-1')
paginator = cloudtrail.get_paginator("lookup_events")
page_iterator = paginator.paginate(
PaginationConfig={'PageSize':1000, 'StartingToken':StartingToken },
StartTime=start_date,
EndTime=end_date)
session_start_time = datetime.datetime.now()
I'd appreciate any help with this.
Thanks in advance
Your solution does not work because you are just shadowing page_iterator variable, so the changes you make to the iterator does not take effect.
You can increase the session length if you are running your script using long-term credentials.
By default, the temporary security credentials created by AssumeRole last for one hour. However, you can use the optional DurationSeconds parameter to specify the duration of your session.
Otherwise, you need to revise the application logic a bit. You can try using a shorter time frame when fetching the trails, e.g. instead of using 1 day, try using 6 hours and slide the time frame accordingly until you fetch all trails you want. This is a better approach in my opinion.

How to make python script update in realtime (run continuously)

Hello I am a beginner in python and I just learned the fundamentals and basics of programming in python. I wanted to make this program that will notify me when my class ends, however, once I run my program it only executes it once
When I loop it, it does not continuously access my date and time (instead it takes the time from when the code is executed). Any suggestion on how to resolve this problem?
import win10toast
import datetime
currentDT = datetime.datetime.now()
toaster = win10toast.ToastNotifier()
while (1):
def Period_A():
if currentDT.hour == 7 and currentDT.minute == 30:
toaster.show_toast('Shedule Reminder', 'It is Period A time!', duration=10)
I wanted the code to run in the background and update the value of the date and time continuously so that the notification will appear on the desired time not the time when the code is executed ;).
The line currentDT = datetime.datetime.now() is only called once throughout the whole program, and therefore stays constant to approximately the time you ran the script.
Since you're want to continuously check the time to compare it to a set time, you'll have to move that line to inside the loop.
Secondly, you define a function Period_A in the loop, which by itself does nothing because you don't call the function. If you don't need the abstraction a function gives you, there is no point in making one just to call it once.
import datetime
import win10toast
toaster = win10toast.ToastNotifier()
while 1:
currentDT = datetime.datetime.now()
if currentDT.hour == 7 and currentDT.minute == 30:
toaster.show_toast('Shedule Reminder', 'It is Period A time!', duration=10)

Python string time [duplicate]

How can I run a function in Python, at a given time?
For example:
run_it_at(func, '2012-07-17 15:50:00')
and it will run the function func at 2012-07-17 15:50:00.
I tried the sched.scheduler, but it didn't start my function.
import time as time_module
scheduler = sched.scheduler(time_module.time, time_module.sleep)
t = time_module.strptime('2012-07-17 15:50:00', '%Y-%m-%d %H:%M:%S')
t = time_module.mktime(t)
scheduler_e = scheduler.enterabs(t, 1, self.update, ())
What can I do?
Reading the docs from http://docs.python.org/py3k/library/sched.html:
Going from that we need to work out a delay (in seconds)...
from datetime import datetime
now = datetime.now()
Then use datetime.strptime to parse '2012-07-17 15:50:00' (I'll leave the format string to you)
# I'm just creating a datetime in 3 hours... (you'd use output from above)
from datetime import timedelta
run_at = now + timedelta(hours=3)
delay = (run_at - now).total_seconds()
You can then use delay to pass into a threading.Timer instance, eg:
threading.Timer(delay, self.update).start()
Take a look at the Advanced Python Scheduler, APScheduler: http://packages.python.org/APScheduler/index.html
They have an example for just this usecase:
http://packages.python.org/APScheduler/dateschedule.html
from datetime import date
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
# Define the function that is to be executed
def my_job(text):
print text
# The job will be executed on November 6th, 2009
exec_date = date(2009, 11, 6)
# Store the job in a variable in case we want to cancel it
job = sched.add_date_job(my_job, exec_date, ['text'])
Might be worth installing this library: https://pypi.python.org/pypi/schedule, basically helps do everything you just described. Here's an example:
import schedule
import time
def job():
print("I'm working...")
schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
while True:
schedule.run_pending()
time.sleep(1)
Here's an update to stephenbez' answer for version 3.5 of APScheduler using Python 2.7:
import os, time
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
def tick(text):
print(text + '! The time is: %s' % datetime.now())
scheduler = BackgroundScheduler()
dd = datetime.now() + timedelta(seconds=3)
scheduler.add_job(tick, 'date',run_date=dd, args=['TICK'])
dd = datetime.now() + timedelta(seconds=6)
scheduler.add_job(tick, 'date',run_date=dd, kwargs={'text':'TOCK'})
scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
scheduler.shutdown()
I've confirmed the code in the opening post works, just lacking scheduler.run(). Tested and it runs the scheduled event. So that is another valid answer.
>>> import sched
>>> import time as time_module
>>> def myfunc(): print("Working")
...
>>> scheduler = sched.scheduler(time_module.time, time_module.sleep)
>>> t = time_module.strptime('2020-01-11 13:36:00', '%Y-%m-%d %H:%M:%S')
>>> t = time_module.mktime(t)
>>> scheduler_e = scheduler.enterabs(t, 1, myfunc, ())
>>> scheduler.run()
Working
>>>
I ran into the same issue: I could not get absolute time events registered with sched.enterabs to be recognized by sched.run. sched.enter worked for me if I calculated a delay, but is awkward to use since I want jobs to run at specific times of day in particular time zones.
In my case, I found that the issue was that the default timefunc in the sched.scheduler initializer is not time.time (as in the example), but rather is time.monotonic. time.monotonic does not make any sense for "absolute" time schedules as, from the docs, "The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid."
The solution for me was to initialize the scheduler as
scheduler = sched.scheduler(time.time, time.sleep)
It is unclear whether your time_module.time is actually time.time or time.monotonic, but it works fine when I initialize it properly.
dateSTR = datetime.datetime.now().strftime("%H:%M:%S" )
if dateSTR == ("20:32:10"):
#do function
print(dateSTR)
else:
# do something useful till this time
time.sleep(1)
pass
Just looking for a Time of Day / Date event trigger:
as long as the date "string" is tied to an updated "time" string, it works as a simple TOD function. You can extend the string out to a date and time.
whether its lexicographical ordering or chronological order comparison,
as long as the string represents a point in time, the string will too.
someone kindly offered this link:
String Comparison Technique Used by Python
had a really hard time getting these answers to work how i needed it to,
but i got this working and its accurate to .01 seconds
from apscheduler.schedulers.background import BackgroundScheduler
sched = BackgroundScheduler()
sched.start()
def myjob():
print('job 1 done at: ' + str(dt.now())[:-3])
dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2000)
job = sched.add_job(myjob, 'date', run_date=Future)
tested accuracy of timing with this code:
at first i did 2 second and 5 second delay, but wanted to test it with a more accurate measurement so i tried again with 2.55 second delay and 5.55 second delay
dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2550)
Future2 = dt.now() + datetime.timedelta(milliseconds=5550)
def myjob1():
print('job 1 done at: ' + str(dt.now())[:-3])
def myjob2():
print('job 2 done at: ' + str(dt.now())[:-3])
print(' current time: ' + str(dt.now())[:-3])
print(' do job 1 at: ' + str(Future)[:-3] + '''
do job 2 at: ''' + str(Future2)[:-3])
job = sched.add_job(myjob1, 'date', run_date=Future)
job2 = sched.add_job(myjob2, 'date', run_date=Future2)
and got these results:
current time: 2020-12-10 19:50:44.632
do job 1 at: 2020-12-10 19:50:47.182
do job 2 at: 2020-12-10 19:50:50.182
job 1 done at: 2020-12-10 19:50:47.184
job 2 done at: 2020-12-10 19:50:50.183
accurate to .002 of a second with 1 test
but i did run a lot of tests and accuracy ranged from .002 to .011
never going under the 2.55 or 5.55 second delay
#everytime you print action_now it will check your current time and tell you should be done
import datetime
current_time = datetime.datetime.now()
current_time.hour
schedule = {
'8':'prep',
'9':'Note review',
'10':'code',
'11':'15 min teabreak ',
'12':'code',
'13':'Lunch Break',
'14':'Test',
'15':'Talk',
'16':'30 min for code ',
'17':'Free',
'18':'Help ',
'19':'watever',
'20':'watever',
'21':'watever',
'22':'watever'
}
action_now = schedule[str(current_time.hour)]

Resources