How to check if midnight has just passed? [closed] - python

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I need a function returning a boolean indicating if midnight has just passed.
I came up with this but I am not happy with the "form". Can anyone think of anything better? as in terms of efficiency/elegance?
from datetime import datetime, timedelta
def passed_midnight(delta=1):
time_now = datetime.today # see other comment below
time_ago = time_now() - timedelta(minutes=delta)
# next line with a dummy delta (zero) cuz "datetime.today - timedelta(days=1)" gives an error
today = time_now() - timedelta(days=0)
return today.strftime("%Y%m%d") != time_ago.strftime("%Y%m%d")
>>> print(passed_midnight, 10)

datetime.today - timedelta(days=1) gives an error because datetime.today is a function that needs to be called. This is why you must have felt the need to write time_now() with parentheses: it's calling the function, twice (with different results, because time has a tendency to pass).
Avoid strftime in favour of date(), which returns the date part only (as a datetime.date object).
Use datetime.now() instead of datetime.today() so that subtracting a timedelta can take the timezone (and hence daylight savings time changeovers) into account.
So then you get this:
from datetime import datetime, timedelta
def passed_midnight(delta=1):
time_now = datetime.now()
time_ago = time_now - timedelta(minutes=delta)
return time_now.date() != time_ago.date()

You probably misunderstood how to declare a function and how to call it.
Here is a version that fixed the issues with function calls:
from datetime import datetime, timedelta
def passed_midnight(delta=1):
today = datetime.today()
time_ago = today - timedelta(minutes=delta)
return today.strftime("%Y%m%d") != time_ago.strftime("%Y%m%d")
>>> print(passed_midnight(10))
False
Be careful, this code doesn't take care of time zones. The behavior will be different from a location to another

Related

How to print message if a date condition is met? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
What would a piece of code look like which checks today's date, and if it's a particular date, it will print out a message?
The context is that I'm making a birthday cake for my son who codes and I want to write a themed Happy Birthday message on top correctly. (Sorry, not as clever or serious as a lot of the things on here!)
I'd like something which is basically:
johnsBirthday = 01/01/1998
johnsAge = todaysdate - johnsBirthday (in years)
if todays date == 01/01/XXXX then print("Happy Birthday John!" + johnsAge + " today!")
My knowledge of python is very limited (as I'm sure you can tell from the above) but I vaguely know how to do this in Excel, so I figure there must be a way to do it in python too?
I know could always just write out:
print("Happy Birthday, John!")
and he'd appreciate that, but I think it would really make him smile to go a little further than that!
# Import datetime class from datetime module
from datetime import datetime
birthday = "20/09/1998"
# Parses the string into a datetime object
birthday_obj = datetime.strptime(birthday, '%d/%m/%Y')
# Gets todays date
now = datetime.now()
# Checks the day and month to verify birthday status
if(birthday_obj.day == now.day and birthday_obj.month == now.month):
johns_age = str(now.year - birthday_obj.year)
print("Happy Birthday John! " + johns_age + " today!")
For your purpose, it might be easier to use regular expressions if you are familiar with them. You can search any patterns you like, after converting datetimes to string, or better yet if you already have datetimes in string formats.
For datetime to string format conversion codes, check out -
format-codes
Example code
import re
from datetime import datetime
pattern = re.compile(r'^01/01/')
today_date = datetime.now().strftime(r'%d/%m/%Y')
some_date = '01/01/2021'
print(re.match(pattern, some_date)) # <re.Match object; span=(0, 6), match='01/01/'>
print(today_date) # 20/09/2020
print(pattern.match(today_date)) # None
Edit - Had forgotten that age needs to be calculated!
import re
from datetime import datetime
johns_birthday = '01/01/1998'
if (re.match('^01/01/', johns_birthday)):
johns_age = datetime.now().year - datetime.strptime(johns_birthday, r'%d/%m/%Y').year
print("Happy Birthday John! " + str(johns_age) + " today!")

can't compare datetime.datetime to builtin_function_or_method [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am new in Django.
I created Sponsor model that model has start_date (start date become sponsor) and end_date (end date of sponsor).
start_date = models.DateField(
_("Start date"),
default=datetime.date.today)
end_date = models.DateField(
_("End date"),
default=datetime.date.today)
I want to put all logic inside the model, if that not possible then I want to put the logic in a view. I make method current_sponsor which can return True or False (if today is on a range of start_date and end_date means True else False).
This is my current_sponsor method
def current_sponsor(self):
today = datetime.date.today
if today >= self.start_date:
return True
elif today <= self.end_date:
return True
else:
return False
The problem is I got error can't compare datetime.datetime to builtin_function_or_method.
I've tried to see the data using django shell it seem works but the reality does not work.
datetime.date.today is not calling the function you think it is:
>>> import datetime
>>> datetime.date.today
<built-in method today of type object at 0x7fb681a90f80> # NOT CALLING FUNCTION
>>> datetime.date.today() # You need () at the end
datetime.date(2015, 11, 4)
If you add the parentheses, you'll get the result you expect.

Make program sleep for X seconds in python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am making an alarm clock program that will have to sleep (Not make noise) until 6:00AM. The problem I am having is that I cannot get the program to wait X seconds
Pseudo Code:
X = 6:00AM - CurrentTime
time.sleep(X)
Here is my code so far:
#Imports
import datetime
import time
import pygame
WORDS = ["Wake", "Me", "Tommorow"]
#Make J.A.R.V.I.S. Listen
mic.activeListen():
#Determine time and difference of time
x = datetime.datetime.now()
x = x.total_seconds
print(x)
x = datetime.timedelta()
x = float(x) #time.sleep() Requires a float value.
time.sleep(x) #Sleeps until 6:00 AM
pygame.mixer.init()
pygame.mixer.music.load("alarm.mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
In order to create a datetime object representing 6:00am, you'd need to specify the date. E.g. if you want 6:00am today (assuming it happens in the future):
from datetime import datetime, date, time, timedelta
import time
d = date.today()
target_dt = datetime.combine(d, time(6,0))
td = target_dt - datetime.now()
time.sleep(td.total_seconds())
If you want 6am tomorrow, do:
d = date.today() + timedelta(days=1)
# the rest is the same...
You should not trust time.sleep() to stop waiting at the expected time, as any caught signal will terminate it (see answers to Upper limit in Python time.sleep()?).

Datetime comparison behavior in python

Hi I am writing a program that is dependent on time and observing some curious behavior with datetime objects I cannot quite figure out. The code I am working with / am having trouble with is...
now = datetime.now()
time_changed_state = some datettime object previously initialized
time_delay = some integer
time_arrival = time_changed_state + timedelta(minutes=time_delay)
if now < time_arrival:
do something
elif now >= time_arrival:
do something different
I have been working with test cases in order ot make sure the code behaves the way I would like it to but it doesn't seem to.
I discovered the odd behavior when the time_delay = 0, and I know for a fact that now would be >= time_arrival since time_changed_state was a datetime object initilizated before this function call and now was initialized within the function. However, the "do something" code is being executed rather than the "do something different code".
Thanks so much!
I've edited your code, is this what you are expecting?
from datetime import datetime
from datetime import timedelta
now = datetime.now()
time_changed_state = now - timedelta(hours=2)
time_delay = 0
time_arrival = time_changed_state + timedelta(minutes=time_delay)
if now < time_arrival:
print 'something'
elif now >= time_arrival:
print 'something different'

In Python, how can I put a thread to sleep until a specific time?

I know that I can cause a thread to sleep for a specific amount of time with:
time.sleep(NUM)
How can I make a thread sleep until 2AM? Do I have to do math to determine the number of seconds until 2AM? Or is there some library function?
( Yes, I know about cron and equivalent systems in Windows, but I want to sleep my thread in python proper and not rely on external stimulus or process signals.)
Here's a half-ass solution that doesn't account for clock jitter or adjustment of the clock. See comments for ways to get rid of that.
import time
import datetime
# if for some reason this script is still running
# after a year, we'll stop after 365 days
for i in xrange(0,365):
# sleep until 2AM
t = datetime.datetime.today()
future = datetime.datetime(t.year,t.month,t.day,2,0)
if t.hour >= 2:
future += datetime.timedelta(days=1)
time.sleep((future-t).total_seconds())
# do 2AM stuff
You can use the pause package, and specifically the pause.until function, for this:
import pause
from datetime import datetime
pause.until(datetime(2015, 8, 12, 2))
Slightly more generalized solution (based off of Ross Rogers') in case you'd like to add minutes as well.
def sleepUntil(self, hour, minute):
t = datetime.datetime.today()
future = datetime.datetime(t.year, t.month, t.day, hour, minute)
if t.timestamp() > future.timestamp():
future += datetime.timedelta(days=1)
time.sleep((future-t).total_seconds())
Another approach, using sleep, decreasing the timeout logarithmically.
def wait_until(end_datetime):
while True:
diff = (end_datetime - datetime.now()).total_seconds()
if diff < 0: return # In case end_datetime was in past to begin with
time.sleep(diff/2)
if diff <= 0.1: return
Building on the answer of #MZA and the comment of #Mads Y
One possible approach is to sleep for an hour. Every hour, check if the time is in the middle of the night. If so, proceed with your operation. If not, sleep for another hour and continue.
If the user were to change their clock in the middle of the day, this approach would reflect that change. While it requires slightly more resources, it should be negligible.
I tried the "pause" pacakage. It does not work for Python 3.x. From the pause package I extracted the code required to wait until a specific datetime and made the following def.
def wait_until(execute_it_now):
while True:
diff = (execute_it_now - datetime.now()).total_seconds()
if diff <= 0:
return
elif diff <= 0.1:
time.sleep(0.001)
elif diff <= 0.5:
time.sleep(0.01)
elif diff <= 1.5:
time.sleep(0.1)
else:
time.sleep(1)
adapt this:
from datetime import datetime, timedelta
from time import sleep
now = datetime.utcnow
to = (now() + timedelta(days = 1)).replace(hour=1, minute=0, second=0)
sleep((to-now()).seconds)
Slightly beside the point of the original question:
Even if you don't want to muck around with crontabs, if you can schedule python scripts to those hosts, you might be interested to schedule anacron tasks? anacron's major differentiator to cron is that it does not rely the computer to run continuously. Depending on system configuration you may need admin rights even for such user-scheduled tasks.
A similar, more modern tool is upstart provided by the Ubuntu folks: http://upstart.ubuntu.com/
This does not yet even have the required features. But scheduling jobs and replacing anacron is a planned feature. It has quite some traction due to its usage as Ubuntu default initd replacement. (I am not affiliated with the project)
Of course, with the already provided answer, you can code the same functionality into your python script and it might suit you better in your case.
Still, for others, anacron or similar existing systems might be a better solution. anacron is preinstalled on many current linux distributions (there are portability issues for windows users).
Wikipedia provides a pointer page: https://en.wikipedia.org/wiki/Anacron
If you do go for a python version I'd look at the asynchronous aspect, and ensure the script works even if the time is changed (daylight savings, etc) as others have commented already. Instead of waiting til a pre-calculated future, I'd always at maximum wait one hour, then re-check the time. The compute cycles invested should be negligible even on mobile, embedded systems.
Asynchronous version of Omrii's solution
import datetime
import asyncio
async def sleep_until(hour: int, minute: int, second: int):
"""Asynchronous wait until specific hour, minute and second
Args:
hour (int): Hour
minute (int): Minute
second (int): Second
"""
t = datetime.datetime.today()
future = datetime.datetime(t.year, t.month, t.day, hour, minute, second)
if t.timestamp() > future.timestamp():
future += datetime.timedelta(days=1)
await asyncio.sleep((future - t).total_seconds())
I know is way late for this, but I wanted to post an answer (inspired on the marked answer) considering systems that might have - incorrect - desired timezone + include how to do this threaded for people wondering how.
It looks big because I'm commenting every step to explain the logic.
import pytz #timezone lib
import datetime
import time
from threading import Thread
# using this as I am, check list of timezone strings at:
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TIMEZONE = pytz.timezone("America/Sao_Paulo")
# function to return desired seconds, even if it's the next day
## check the bkp_time variable (I use this for a bkp thread)
## to edit what time you want to execute your thread
def get_waiting_time_till_two(TIMEZONE):
# get current time and date as our timezone
## later we remove the timezone info just to be sure no errors
now = datetime.datetime.now(tz=TIMEZONE).replace(tzinfo=None)
curr_time = now.time()
curr_date = now.date()
# Make 23h30 string into datetime, adding the same date as current time above
bkp_time = datetime.datetime.strptime("02:00:00","%H:%M:%S").time()
bkp_datetime = datetime.datetime.combine(curr_date, bkp_time)
# extract the difference from both dates and a day in seconds
bkp_minus_curr_seconds = (bkp_datetime - now).total_seconds()
a_day_in_seconds = 60 * 60 * 24
# if the difference is a negative value, we will subtract (- with + = -)
# it from a day in seconds, otherwise it's just the difference
# this means that if the time is the next day, it will adjust accordingly
wait_time = a_day_in_seconds + bkp_minus_curr_seconds if bkp_minus_curr_seconds < 0 else bkp_minus_curr_seconds
return wait_time
# Here will be the function we will call at threading
def function_we_will_thread():
# this will make it infinite during the threading
while True:
seconds = get_waiting_time_till_two(TIMEZONE)
time.sleep(seconds)
# Do your routine
# Now this is the part where it will be threading
thread_auto_update = Thread(target=function_we_will_thread)
thread_auto_update.start()
It takes only one of the very basic libraries.
import time
sleep_until = 'Mon Dec 25 06:00:00 2020' # String format might be locale dependent.
print("Sleeping until {}...".format(sleep_until))
time.sleep(time.mktime(time.strptime(sleep_until)) - time.time())
time.strptime() parses the time from string -> struct_time tuple. The string can be in different format, if you give strptime() parse-format string as a second argument. E.g.
time.strptime("12/25/2020 02:00AM", "%m/%d/%Y %I:%M%p")
time.mktime() turns the struct_time -> epoch time in seconds.
time.time() gives current epoch time in seconds.
Substract the latter from the former and you get the wanted sleep time in seconds.
sleep() the amount.
If you just want to sleep until whatever happens to be the next 2AM, (might be today or tomorrow), you need an if-statement to check if the time has already passed today. And if it has, set the wake up for the next day instead.
import time
sleep_until = "02:00AM" # Sets the time to sleep until.
sleep_until = time.strftime("%m/%d/%Y " + sleep_until, time.localtime()) # Adds todays date to the string sleep_until.
now_epoch = time.time() #Current time in seconds from the epoch time.
alarm_epoch = time.mktime(time.strptime(sleep_until, "%m/%d/%Y %I:%M%p")) # Sleep_until time in seconds from the epoch time.
if now_epoch > alarm_epoch: #If we are already past the alarm time today.
alarm_epoch = alarm_epoch + 86400 # Adds a day worth of seconds to the alarm_epoch, hence setting it to next day instead.
time.sleep(alarm_epoch - now_epoch) # Sleeps until the next time the time is the set time, whether it's today or tomorrow.
What about this handy and simple solution?
from datetime import datetime
import time
pause_until = datetime.fromisoformat('2023-02-11T00:02:00') # or whatever timestamp you gonna need
time.sleep((pause_until - datetime.now()).total_seconds())
from datetime import datetime
import time, operator
time.sleep([i[0]*3600 + i[1]*60 for i in [[H, M]]][0] - [i[0]*3600 + i[1]*60 for i in [map(int, datetime.now().strftime("%H:%M").split(':'))]][0])
Instead of using the wait() function, you can use a while-loop checking if the specified date has been reached yet:
if datetime.datetime.utcnow() > next_friday_10am:
# run thread or whatever action
next_friday_10am = next_friday_10am()
time.sleep(30)
def next_friday_10am():
for i in range(7):
for j in range(24):
for k in range(60):
if (datetime.datetime.utcnow() + datetime.timedelta(days=i)).weekday() == 4:
if (datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j)).hour == 8:
if (datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j, minutes=k)).minute == 0:
return datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j, minutes=k)
Still has the time-checking thread check the condition every after 30 seconds so there is more computing required than in waiting, but it's a way to make it work.

Categories

Resources