I am working on a website with weekly votations, but only the first three weeks of the month, so in each instance I have a start_date and end_date field.
I'd like to know if there's a way to automitically create these instances based on the current date, for instance:
Today it is 6 of March, and votations end tomorrow, so a function should be run (tmrw) that, taking into account this month calendar, would fill in the appropiate dates for the next votations. What calendar do you recommend me, and how shoul I do it?
(Never mind the automatically run part, I'll go with celery).
Thanks!
I am not sure what your problem is and I don't know what votations are. But as a general direction of thinking: there is timeboard library that can generate rule-based schedules (calendars) and do calculations over them (DISCLAIMER: I am the author).
The code below designates, for every month of 2018, the days of the first three weeks of the month as 'on-duty' (i.e. 'active', 'usable') and the rest as 'off-duty':
>>> import timeboard as tb
>>> weekly = tb.Organizer(marker='W', structure=[[1],[1],[1],[0],[0],[0]])
>>> monthly = tb.Organizer(marker='M', structure=[weekly])
>>> clnd = tb.Timeboard(base_unit_freq='D',
... start='01 Jan 2018', end='31 Dec 2018',
... layout=monthly)
For example, in March 2018, the days from Thursday, 1st, through Sunday, 18th, are marked 'on-duty', and the days 19-31 are marked 'off-duty'.
Now you can move along the calendar picking only on-duty days. For example, adding 1 to March, 17 gives you March 18:
>>> (clnd('17 Mar 2018') + 1).to_timestamp()
Timestamp('2018-03-18 00:00:00')
However, adding 2 carries you over to April 1, as March 19 is NOT within the first 3 weeks of March:
>>> (clnd('17 Mar 2018') + 2).to_timestamp()
Timestamp('2018-04-01 00:00:00')
Related
Oracle has a very useful function for finding the date of the next weekday. This function is called NEXT_DAY. It takes a start date, say 15-OCT-2009, and the weekday we're expecting, say TUESDAY. The result of NEXT_DAY('15-OCT-2009', 'TUESDAY') is 20-OCT-2009 because that's the next Tuesday after the 15th of October 2009.
Does Python have a function, be it Built-in or via the datetime library, that does this same thing?
I need it to deterministically return true/false for the question "if this day was in November, is it Thanksgiving?" without referencing any kind of lookup table for any year.
It's used by looking at the day number, the 15th part from above, and finding the number of days until the next Thursday in October then adding 21 to that. An alternative method of answering the question "is the day Thanksgiving?", deterministically, at runtime, without any lookup tables, restricted to plain Python or the datetime library would work for my situation but would not work to answer the question in the title.
I think this should work.
from datetime import datetime,timedelta
def next_day(date, day_of_week):
if date.weekday() == day_of_week:
return (date + timedelta(days=7)).date()
else:
return (date + timedelta(days=(day_of_week - date.weekday() + 7) % 7)).date()
# Test
day_names = "mon tue wed thu fri sat sun".split()
now = datetime.now()
print(f"Today is {day_names[now.weekday()]}, {now.date()}")
for i in range(7):
print(f"next {day_names[i]}: {next_day(now, i)}")
Ouput
Today is thu, 2023-02-16
next mon: 2023-02-20
next tue: 2023-02-21
next wed: 2023-02-22
next thu: 2023-02-23
next fri: 2023-02-17
next sat: 2023-02-18
next sun: 2023-02-19
Have a look at Delorean (need to install via pip) and it's natural language capabilities
e.g. finding Thanksgiving for given year
import delorean as dl
from datetime import datetime
year = int(input('Enter a year:'))
d = dl.Delorean(datetime(year,11,30), timezone='UTC')
print(f"In {year} Thanksgiving is {d.last_thursday().date}")
output
Enter a year:2023
In 2023 Thanksgiving is on 2023-11-23
Enter a year:2022
In 2022 Thanksgiving is 2022-11-24
or finding next Monday
print(dl.Delorean(datetime.now(), timezone='utc').next_monday().date)
output
2023-02-20
I have a dataframe similar to the following one:
df = pd.DataFrame({'Text': ['Hello I would like to get only the date which is 12-13 December 2018 amid this text.', 'Ciao, what I would like to do is to keep dates, e.g. 11-14 October 2019, and remove all the rest.','Hi, SO can you help me delete everything but 10 January 2011. I found it hard doing it myself.']})
I would like to extract only dates from the text. The problem is that it is hard to find patterns. The only rule I can find there is: keep 2/3 objects before a four-digit number (i.e. the year).
I tried many convoluted solutions but I am not able to get what I need.
The result should look like this:
["12-13 December 2018"
"11-14 October 2019"
"10 January 2011"]
Can anyone help me?
Thanks!
If "keep 2/3 object before a four-digit number (i.e. the year)" is a reliable rule then you could use the following:
import re
data = {'Text': ['Hello I would like to get only the date which is 12-13 December 2018 amid this text.', 'Ciao, what I would like to do is to keep dates, e.g. 11-14 October 2019, and remove all the rest.','Hi, SO can you help me delete everything but 10 January 2011. I found it hard doing it myself.']}
date_strings = []
for string in data['Text']: # loop through each string
words = string.split() # split string by ' ' characters
for index in range(len(words)):
if re.search(r'(\d){4}', words[index]): # if the 'word' is 4 digits
date_strings.append( ' '.join(words[index-2:index+1]) ) # extract that word & the preceeding 2
break
print(date_strings)
To get:
['12-13 December 2018', '11-14 October 2019,', '10 January 2011.']
Some assumptions:
the dates are always 3 'words' long
the years are always at the end of the dates
as pointed out in the comments, the only 4-digit number in the text is the year
Here is a potential solution using a regex:
from calendar import month_name
months = '|'.join(list(month_name)[1:])
df['Text'].str.extract(r'([0-9-]+ (?:%s) \d{4})' % months)[0]
alternative regex: r'((?:\d+-)?\d+ (?:%s) \d{4})' % months
output:
0 12-13 December 2018
1 11-14 October 2019
2 10 January 2011
I want to get the week number corresponding to the UK fiscal year (which runs 6th April to 5th April). report_date.strftime('%V') will give me the week number corresponding to the calendar year (1st January to 31st December).
For example, today is 2nd February which is UK fiscal week 44, but %V would return 05.
I've seen the https://pypi.org/project/fiscalyear/ library but it doesn't seem to offer a way to do this. I know that I can work out the number of days since April 6th and divide by 7, but just curious if there's a better way.
This does the job in Python. It counts the number of days since April 6th of the given year (formatted_report_date), and if the answer is negative (because April 6th hasn't passed yet), then a year is subtracted. Then divide by 7 and add 1 (for 1-indexing). The answer will be between 1-53.
def get_fiscal_week(formatted_report_date):
"""
Given a date, returns the week number (from 1-53) since the last April 6th.
:param formatted_report_date: the formatted date to be converted into a
fiscal week.
"""
from datetime import datetime
fiscal_start = formatted_report_date.replace(month=4, day=6)
days_since_fiscal_start = (formatted_report_date - fiscal_start).days
if days_since_fiscal_start < 0:
fiscal_start = fiscal_start.replace(year=fiscal_start.year-1)
days_since_fiscal_start = (formatted_report_date - fiscal_start).days
return (days_since_fiscal_start / 7) + 1
Any idea how to localize a date, which should only displays day and month respectively month and day?
I know how to format the whole date:
formats.date_format(datetime.now(), format="DATE_FORMAT", use_l10n=True)
Which returns the date as: Feb. 6, 2020 or 6 Feb. 2020 according to the locale setting.
I need the same Output, but without the year.
You can use MONTH_DAY_FORMAT.
formats.date_format(datetime.now(), format="MONTH_DAY_FORMAT", use_l10n=True)
Scenario A:
Suppose the current time is 3 am on Jan 12th, 2014, I want to get two times in past for midnight just before 3 am and noon just before 3 am
So, I am looking at getting 00:00 hours of Jan 12th and noon of Jan 11th from the current time of 3 am on Jan 12th, 2014
Scenario B:
Suppose the current time is 6:37 pm on Jan 13th, 2014, I want to get two times in past for midnight just before 6:37 pm and noon just before 3 pm
So, I am looking at getting 00:00 hours of Jan 13th and noon of Jan 13th for the current time of 6:37 pm on Jan 13th, 2014
The times can be in epoch - I am just not able to figure out the math to get the two times given a current time.
Can someone help me out?
You can combine a date and time using datetime.datetime.combine, so you can get just the current date:
today = datetime.datetime.now().date()
Create your times, e.g.:
midday = datetime.time(hour=12)
And add them together, e.g.:
midday_today = datetime.datetime.combine(today, midday)
This is much less complicated than trying to add or subtract times from the current time. To decide whether you want today or yesterday, you can check whether we are before or after midday:
if datetime.datetime.now().time() < midday:
Putting this together:
import datetime
now = datetime.datetime.now()
today = now.date()
midnight = datetime.time(hour=0)
midday = datetime.time(hour=12)
last_midnight = datetime.datetime.combine(today, midnight)
if now.time() < midday:
yesterday = today - datetime.timedelta(days=1)
last_midday = datetime.datetime.combine(yesterday, midday)
else:
last_midday = datetime.datetime.combine(today, midday)