Pandas timestamp function - python

For a school project, I am writing a function that takes in a datetime variable. If the datetime_variable.day_name() != 'Friday' I need to subtract a day until the day_name is equal to Friday. I wrote what I thought was a recursive function to do this, however my loop never ends.
def getDateSplit(date_variable):
from datetime import timedelta
max_date = date_variable
print('Max Date:', max_date, 'Day of Week:', max_date.day_name())
if(max_date.day_name() == 'Friday'):
return max_date
else:
return getDateSplit(max_date - timedelta(days = 1))

The following minimally adapted version will work:
def getDateSplit(date_variable):
if date_variable.day_name() == "Friday":
return date_variable
return getDateSplit(date_variable - timedelta(days=1))
Example usage:
date_variable = pd.to_datetime("2018-01-01")
date_variable.day_name() # "Monday"
friday_before = getDateSplit(date_variable)
friday_before # Timestamp('2017-12-29 00:00:00')
friday_before.day_name() # "Friday"

For anyone that cares, I went away from recursion. Not that cool yet. Here's my solution:
def getDateSplit(date_variable):
from datetime import timedelta
max_date = date_variable
while(max_date.day_name() != 'Friday'):
print('Max Date:', max_date, 'Day of Week:', max_date.day_name())
max_date -= timedelta(days = 1)
return max_date

Related

How to check given date is exactly a month ago : python

I need to check if a given date is exactly a month ago from today, for example, if today is 01-Nov-2021 then exactly a month ago will be 01-Oct-2021 (not exactly 30 days.)
I wrote a code and it works fine
today = fields.Date.from_string(fields.Date.today())
if today.month == 1:
one_month_ago = today.replace(year=today.year - 1, month=12)
else:
extra_days = 0
while True:
try:
one_month_ago = today.replace(month=today.month - 1, day=today.day -
extra_days)
break
except ValueError:
extra_days += 1
if one_month_ago == given_date:
# do something
else:
# do something
It handles well mostly all the cases but mishandles some cases. For example, the given date is 31-March-2021 and today date is 30-April-2021 and 31-April-2021 will not come to compare. I need my code to run daily and check something. It also mishandles cases of 29-31 January because 29-31 February will not come to compare.
From the given date, you can find the previous month and year and using these two obtained values, find the length of the previous month. The last thing to be done will be to compare the day of the given date with the length of the previous month and accordingly, return the desired date.
Demo:
from datetime import date
from calendar import monthrange
def date_a_month_ago(today):
x = today.month - 1
previous_month = 12 if x == 0 else x
year = today.year - 1 if x == 0 else today.year
last_day_of_previous_month = monthrange(year, previous_month)[1]
day = last_day_of_previous_month if today.day > last_day_of_previous_month else today.day
return date(year, previous_month, day)
# Tests
print(date_a_month_ago(date(2021, 11, 1)))
print(date_a_month_ago(date(2021, 1, 31)))
print(date_a_month_ago(date(2021, 12, 31)))
print(date_a_month_ago(date(2021, 3, 29)))
print(date_a_month_ago(date(2020, 3, 29)))
print(date_a_month_ago(date(2021, 3, 30)))
print(date_a_month_ago(date(2020, 3, 30)))
Output:
2021-10-01
2020-12-31
2021-11-30
2021-02-28
2020-02-29
2021-02-28
2020-02-29
ONLINE DEMO
May be like this:
from typing import Tuple
def last_month(year: int, month: int) -> Tuple[int, int]:
y, m = year, month - 1
if m == 0:
y, m = y - 1, 12
return y, m
def one_month_ago(today: datetime) -> datetime:
y, m = last_month(today.year, today.month)
dt = today.replace(year=y, month=m)
for day in range(today.day, 0, -1):
try:
return dt.replace(day=day)
except ValueError:
...
I did this and it's giving me the required output:
from datetime import date
from calendar import monthrange
def is_one_month(given_date, today):
x = today.month - 1
previous_month = 12 if x == 0 else x
year = today.year - 1 if x == 0 else today.year
last_day_of_previous_month = monthrange(year, previous_month)[1]
day = last_day_of_previous_month if today.day > last_day_of_previous_month else today.day
one_month_ago = date(year, previous_month, day)
if today.month == 2:
if given_date.month == today.month-1 and given_date.year == today.year and given_date.day >= 28:
return 'it is one month before'
if today.month == 4 or today.month == 6 or today.month == 9 or today.month == 11:
if given_date.month == today.month-1 and given_date.day == 31:
return 'it is one month before'
if one_month_ago == given_date:
return 'it is one month before'
else:
return 'it is NOT one month before'
print(is_one_month(date(2021, 1, 30), date(2021, 2, 28)))
Output:
it is one month before

Python difference between partially known dates

I am trying to calculate the difference between the current date and a given (partially known) date. For example: Valid date formats (YYYY-MM-DD) are listed below.
YYYY-MM-DD
YYYY-MM-??
YYYY-??-??
????-??-??
Examples, for the current day (2021-07-04), the results would then be
2021-12-02 -> 0 years, 5 months, however many days.
2022-06-?? -> 1 year, however many months
2077-??-?? -> ~56 Years
????-??-?? -> Unknown
So basically, when there is a ??, that part is ignore and we only check the next higher part of the date, e.g. if the day is marked with ?? we only look at year and month etc.
Here is what I've thrown together so far:
#staticmethod
def calculate_time_left(release_date):
# Only year is known:
if re.match("([0-9]{4})-\?\?-\?\?", release_date):
release_year = int(re.search("([0-9]{4})-\?\?-\?\?", release_date).group(1))
current_year = int(datetime.datetime.now().year)
if release_year == current_year:
return "This year."
else:
return "~{} year(s).".format(release_year - current_year)
elif re.match("([0-9]{4})-([0-9]{2})-\?\?", release_date):
release_year = int(re.search("([0-9]{4})-([0-9]{2})-\?\?", release_date).group(1))
current_year = int(datetime.datetime.now().year)
release_month = int(re.search("([0-9]{4})-([0-9]{2})-\?\?", release_date).group(2))
current_month = int(datetime.datetime.now().month)
if release_year == current_year:
if release_month == current_month:
return "This month"
else:
return "~{} months".format(release_month - current_month)
else:
return "{} year(s) and {} months.".format(release_year - current_year, release_month - current_month)
elif re.match("([0-9]{4})-([0-9]{2})-([0-9]{2})", release_date):
release_year = int(re.search("([0-9]{4})-([0-9]{2})-([0-9]{2})", release_date).group(1))
current_year = int(datetime.datetime.now().year)
release_month = int(re.search("([0-9]{4})-([0-9]{2})-([0-9]{2})", release_date).group(2))
current_month = int(datetime.datetime.now().month)
release_day = int(re.search("([0-9]{4})-([0-9]{2})-([0-9]{2})", release_date).group(3))
current_day = int(datetime.datetime.now().day)
if release_year == current_year:
if release_month == current_month:
if release_day == current_day:
return "Today."
else:
return "{} days.".format(release_day - current_day)
else:
if release_day == current_day:
"~{} months.".format(release_month - current_month)
else:
return "~{} months and {} days.".format(release_month - current_month, release_day - current_day)
else:
if release_month == current_month:
if release_day == current_day:
return "{} year(s).".format(release_year - current_year)
else:
if release_day == current_day:
return "{} year(s) and {} months.".format(release_year - current_year, release_month - current_month)
else:
return "{} year(s), {} months and {} days.".format(release_year - current_year, release_month - current_month, release_day - current_day)
return "Release date unknown."
I am having a couple of problems here:
I am getting negative values for the differences of months and days. For example 2022-01-02 would return 1 year(s), -6 months and -2 days.
I feel like I don't need to do all this regex matching for every case. There is probably a better way to do this.
How do I solve this properly? I feel like my approach is pretty poor and error prone.
For the negative values, you can just use absolute value function to remove the negative. i am still looking at your code trying to figure out what you are trying to accomplish. Is this just for practice ? Also, since you are not using the script as an actual date for any real purpose, just treat the each part of the date (yyyy) (mm) (dd) , as a regular integer. No, I don't think you need regex just to figure this out but its good that you know a bit of regex. Treat the numbers as integers and just format them according to how you want to display the output. I am still learning python myself, just my two cents.
I'm not sure what your overall algo should return, but here is a way to evaluate the parts of the dates:
for date_string in ['2021-12-02', '2022-06-??', '2077-??-??', '????-??-??']:
year, month, day = date_string.split('-')
year_delta = month_delta = day_delta = 'unknown'
if year.count('?') == 0: # if there are no ? in the year string
year_delta = int(year) - datetime.now().year
if month.count('?') == 0:
month_delta = int(month) - datetime.now().month
if day.count('?') == 0:
day_delta = int(day) - datetime.now().day

applying a FOR loop to a function

good day! How to properly apply a FOR loop to a given function?
thanks for the tips:)
from datetime import timedelta
from apps.tickets.models import PatientConsultationTicket
def tickets_change():
tickets = PatientConsultationTicket.object.all()
one_day = tickets.created_at + timedelta(days=1)
if datetime.now() > one_day:
tickets.status = 'rd'
tickets.save()
elif datetime.now() < one_day:
tickets.status = 'e'
tickets.save()
To answer your question that's how you can iterate on the tickets :
from datetime import timedelta
from apps.tickets.models import PatientConsultationTicket
def tickets_change():
tickets = PatientConsultationTicket.objects.all()
for ticket in tickets:
one_day = ticket.created_at + timedelta(days=1)
if datetime.now() > one_day:
ticket.status = 'rd'
ticket.save()
elif datetime.now() < one_day:
ticket.status = 'e'
ticket.save()
Though, it's probably not the best way to do what you want.
Instead you should probably use an "UPDATE" query (not tested but it could look to something like that):
PatientConsultationTicket.objects.filter(created_at__gte=datetime.now()-timedelta(days=1)).update(status='rd')
PatientConsultationTicket.objects.filter(created_at__lte=datetime.now()-timedelta(days=1)).update(status='e')

how do you program a calendar that can tell you the days ago/ from now (past/future dates) of a specific date you enter in

I am trying to program a calendar that checks how many days from now/ ago (past and present) from raw_input. I need a loop that counts the days through the current year and adds it to a variable called: Total_days and this loop has to go through each year until it hits the current date that the code ran on. The end result is that the output gives you the date you entered in a complete sentence: eg. "10/08/1700 was ___ days ago" Basically my teacher explained that the past days has to add up until it hits that certain date using a loop(loops are required. This is an assignment, i cant use any other functions like delta, but loops and datetime stuff is good!) and then for the future it has to say how many days from now until that futuristic date happens using loops. I am very stumped and i need your guys' help.
Heres what i got so far:
import datetime
input_date = raw_input("Enter in full format (mm/dd/yyyy):")
year = input_date[6:10]
yeara = int(year)
montha = int(input_date[1:2])
daya = int(input_date[4:5])
from datetime import datetime
from datetime import date
now = datetime.now()
year = now.year
month = now.month
day = now.day
def isleapYear(year):
if year % 4 == 0:
check = True
if year % 100 == 0:
check = False
if year % 400 == 0:
check = True
total_days = 0
n = 12
moNum = [0,31,28,31,30,31,30,31,31,30,31,30,31]
while n > montha:
if yeara > year:
if year == isleapYear(year):
total_days += 366
elif year != isleapYear(year):
total_days += 365
if montha == month:
break
total_days += int(moNum[n])
if n == 02:
if isleapYear(year) == True:
total_days += 1
n -= 1
ny = 365
h = total_days
if yeara > year:
if year == isleapYear(year):
total_days += 366
elif year != isleapYear(year):
total_days += 365
if yeara>year:
time = "future"
if yeara<year:
time = "past"
if yeara==year:
if montha>month:
time = "future"
if montha<month:
time = past
if montha == month:
if daya>day:
time = "future"
if daya<day:
time = "past"
if daya==day:
time = "present"
print str(h.days) + " days in the " + str(time)
Thanks for helping out! i appreciate your help :)
Must you use a loop? Else, you can build from the following:
refdatestr = "2010/08/23"
refdate = datetime.strptime(refdatestr, "%Y/%m/%d")
now = datetime.now()
difference_days = (now-refdate).days
difference_days is a datetime.timedelta object. If refdate (or refdatestr) was in the future, this would be negative.
Here is an updated code, with everything fixed:
import datetime
input_date = raw_input("Enter in full format (mm/dd/yyyy):")
year = input_date[6:10]
yeara = int(year)
montha = int(input_date[1:2])
daya = int(input_date[4:5])
from datetime import datetime
from datetime import date
now = datetime.now()
year = now.year
month = now.month
day = now.day
def isleapYear(year):
if year % 4 == 0:
check = True
if year % 100 == 0:
check = False
if year % 400 == 0:
check = True
end_date = input_date
start_date = now
delta = date(year,month,day)
delta2 = date(yeara,montha,daya)
h = delta-delta2
if yeara>year:
time = "future"
if yeara<year:
time = "past"
if yeara==year:
if montha>month:
time = "future"
if montha<month:
time = past
if montha == month:
if daya>day:
time = "future"
if daya<day:
time = "past"
if daya==day:
time = "present"
print str(h.days) + " in the " + str(time)
The most important thing that you forgot is that there are functions in datetime that will automatically find the number of days till the input...
Hope this helps!!!

How to compare hours and minutes?

I have four variables:
start_hour = '12'
start_minute = '00'
end_hour = '22'
end_minute = '30'
and from datetime:
current_hour = datetime.now().hour
curren_minute = datetime.now().minute
And I want to compare if the current time is within the range:
if int(start_hour) <= current_hour and int(end_hour) >= current_hour:
something
But how to implement this with minutes?
You can use datetime.timedelta to do the comparisons reliably. You can specify a delta in different units of time (hours, minutes, seconds, etc.) Then you don't have to worry about converting to hours, minutes, etc. explicitly.
For example, to check if the current time is more than an hour from the start_time:
if abs(datetime.now() - start_time) > datetime.timedelta(hours=1):
# Do thing
You can also use timedelta to shift a time by a given amount:
six_point_five_hours_from_now = datetime.now() + datetime.timedelta(hours=6, minutes=30)
The nice thing about timedelta apart from easy conversions between units is it will automatically handle time differences that span multiple days, etc.
A much better way to go about this would beto convert both times to minutes:
start_time = int(start_hour)*60 + int(start_minute)
end_time = int(end_hour)*60 + int(end_minute)
current_time = datetime.now().hour*60 +datetime.now().minute
if start_time <= current_time and end_time >= current_time:
#doSomething
If you need to include seconds, convert everything to seconds.
What about:
>>> import datetime
>>> now = datetime.datetime.now()
>>> breakfast_time = now.replace( hour=7, minute=30, second=0, microsecond=0 )
>>> lunch_time = now.replace( hour=12, minute=30, second=0, microsecond=0 )
>>> coffee_break = now.replace( hour=16, minute=00, second=0, microsecond=0 )
>>> breakfast_time <= lunch_time <= coffee_break
True
A simple and clear way to do it all with just datetime objects is:
now = datetime.now()
start = now.replace(hour = int(start_hour), minute = int(start_minute))
end = now.replace(hour = int(end_hour), minute = int(end_minute))
if start <= now <= end:
print('something')

Categories