Python Forum

Full Version: datetime module question
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Basically i want to make a list of days and dates for the current month. I want to be able to make the list as options in an optionmenu widget. The format should be for example "Friday 13th October 2023". the variable should be a list of strings. Please help.
So far i got the current year and month from the datetime.now method using the .year/month attribute. I have managed to grab the name of the day by using

todate=datetime.today().strftime("%A")
Here is one way. It's set to display the current day plus next 31 days

from datetime import datetime, timedelta

def ord2(n):
    return str(n) + (
        "th" if 4 <= n % 100 <= 20 else {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th")
    )

def formatter():
    dates = []
    date_start = datetime.now()
    day = datetime.now().strftime('%d')
    day = ord2(int(day))
    dates.append(date_start.strftime(f'%A {day} %B %Y'))
    for i in range(1, 31):
        date_end = datetime.now() + timedelta(days=i)
        day = date_end.strftime('%d')
        day = ord2(int(day))
        dates.append(date_end.strftime(f'%A {day} %B %Y'))
    return dates
    

for days in formatter():
    print(days)
Output:
Thursday 12th October 2023 Friday 13th October 2023 Saturday 14th October 2023 Sunday 15th October 2023 Monday 16th October 2023 Tuesday 17th October 2023 Wednesday 18th October 2023 Thursday 19th October 2023 Friday 20th October 2023 Saturday 21st October 2023 Sunday 22nd October 2023 Monday 23rd October 2023 Tuesday 24th October 2023 Wednesday 25th October 2023 Thursday 26th October 2023 Friday 27th October 2023 Saturday 28th October 2023 Sunday 29th October 2023 Monday 30th October 2023 Tuesday 31st October 2023 Wednesday 1st November 2023 Thursday 2nd November 2023 Friday 3rd November 2023 Saturday 4th November 2023 Sunday 5th November 2023 Monday 6th November 2023 Tuesday 7th November 2023 Wednesday 8th November 2023 Thursday 9th November 2023 Friday 10th November 2023 Saturday 11th November 2023
from calendar import Calendar
from datetime import date
year, month, *_ = date.today().timetuple()
cal = Calendar()
dates = [dt.strftime('%a %d %B %Y') for dt in cal.itermonthdates(year, month) if dt.month == month]
print(dates)
Output:
['Sun 01 October 2023', 'Mon 02 October 2023', 'Tue 03 October 2023', 'Wed 04 October 2023', 'Thu 05 October 2023', 'Fri 06 October 2023', 'Sat 07 October 2023', 'Sun 08 October 2023', 'Mon 09 October 2023', 'Tue 10 October 2023', 'Wed 11 October 2023', 'Thu 12 October 2023', 'Fri 13 October 2023', 'Sat 14 October 2023', 'Sun 15 October 2023', 'Mon 16 October 2023', 'Tue 17 October 2023', 'Wed 18 October 2023', 'Thu 19 October 2023', 'Fri 20 October 2023', 'Sat 21 October 2023', 'Sun 22 October 2023', 'Mon 23 October 2023', 'Tue 24 October 2023', 'Wed 25 October 2023', 'Thu 26 October 2023', 'Fri 27 October 2023', 'Sat 28 October 2023', 'Sun 29 October 2023', 'Mon 30 October 2023', 'Tue 31 October 2023']
(Oct-12-2023, 11:01 AM)jacksfrustration Wrote: [ -> ]Basically i want to make a list of days and dates for the current month. I want to be able to make the list as options in an optionmenu widget. The format should be for example "Friday 13th October 2023". the variable should be a list of strings. Please help.
So far i got the current year and month from the datetime.now method using the .year/month attribute. I have managed to grab the name of the day by using

todate=datetime.today().strftime("%A")

is there a way that i can get a list of the days that have already passed? So for example the list should contain dates +/- 4/5 days. So if the user opens the app now he sees the days and dates of 7th of octoboer to 15th of october
(Oct-12-2023, 01:39 PM)buran Wrote: [ -> ]
from calendar import Calendar
from datetime import date
year, month, *_ = date.today().timetuple()
cal = Calendar()
dates = [dt.strftime('%a %d %B %Y') for dt in cal.itermonthdates(year, month) if dt.month == month]
print(dates)
Output:
['Sun 01 October 2023', 'Mon 02 October 2023', 'Tue 03 October 2023', 'Wed 04 October 2023', 'Thu 05 October 2023', 'Fri 06 October 2023', 'Sat 07 October 2023', 'Sun 08 October 2023', 'Mon 09 October 2023', 'Tue 10 October 2023', 'Wed 11 October 2023', 'Thu 12 October 2023', 'Fri 13 October 2023', 'Sat 14 October 2023', 'Sun 15 October 2023', 'Mon 16 October 2023', 'Tue 17 October 2023', 'Wed 18 October 2023', 'Thu 19 October 2023', 'Fri 20 October 2023', 'Sat 21 October 2023', 'Sun 22 October 2023', 'Mon 23 October 2023', 'Tue 24 October 2023', 'Wed 25 October 2023', 'Thu 26 October 2023', 'Fri 27 October 2023', 'Sat 28 October 2023', 'Sun 29 October 2023', 'Mon 30 October 2023', 'Tue 31 October 2023']


thats closer to what i need. Is there a way to automatically slice the list you provided me with in order to display the past 5 and upcoming 5 days? Cause i tried using the list you provided me in the optionmenu but isntead of the menu opening in vertical fashion it opened in horizontal orientation and i could not choose just one element for some weird reason
Don't know what gui you're using but, can use * to expand
example
from calendar import Calendar
from datetime import date

import tkinter as tk

year, month, *_ = date.today().timetuple()
cal = Calendar()
dates = [dt.strftime(f'%a %d %B %Y') for dt in cal.itermonthdates(year, month) if dt.month == month]

root = tk.Tk()
var = tk.StringVar()
var.set('Choose')
menu = tk.OptionMenu(root, var, *dates)
menu.pack()
root.mainloop()
Another way
from datetime import datetime, timedelta
import tkinter as tk

def formatter():
    dates = []
    cur_date = datetime.now()
    dates.append(cur_date.strftime('%A %d %B %Y'))
    for i in range(1,5):
        start_date = datetime.now() - timedelta(days=i)
        dates.append(start_date.strftime('%A %d %B %Y'))
    dates.reverse()

    for i in range(1,5):
        end_date = datetime.now() + timedelta(days=i)
        dates.append(end_date.strftime('%A %d %B %Y'))
    
    return dates

root = tk.Tk()
root.minsize(400,400)
var = tk.StringVar()
var.set(datetime.now().strftime('%A %d %B %Y'))
optionmenu = tk.OptionMenu(root, var, *formatter())
optionmenu['font'] = None, 12, 'normal'
optionmenu.pack(side='top', fill='x')
root.mainloop()
I am not a fan of OptionMenu. The way __init__() uses *args is antiquated, and it takes a lot of work to change the menu options after an OptionMenu is created. I much prefer using Combobox. The only problem with Combobox is the authors thought it should only be used to select a value, never to call a command function. Sure you can bind to the ComboboxSelected event, but having a widget call a function when the value changes should not require an additional line of code.

To demonstrate what a mess the OptionMenu is, here is an OptionMenu that used to select a date.
from datetime import datetime, timedelta
import tkinter as tk


class DateOptionMenu(tk.OptionMenu):
    """An OptionMenu for selecting from some dates."""

    default_format = "%A %d %B %Y"

    def __init__(self, parent, dates=None, selection=0, format=None, **kwargs):
        self.command = kwargs.pop("command") if "command" in kwargs else None
        self.format = format or self.default_format
        self.datestr = tk.StringVar()
        super().__init__(parent, self.datestr, "", "")  # Empty for now.  Fill later
        self.configure(**kwargs)  # Required because OptionMenu is poorly designed
        if dates:
            self.set_dates(dates, selection)

    def _select_cb(self, datestr):
        """Called when selection made.  Update display and call command(date)."""
        self.datestr.set(datestr)
        self.date = datetime.strptime(datestr, self.format)
        if self.command:
            self.command(self.date)

    def set_dates(self, dates, selection=0):
        """Set dates to select from.  Make initialial selections"""
        menu = self["menu"]
        menu.delete(0, tk.END)
        for date in dates:
            ds = date.strftime(self.format)
            menu.add_command(label=ds, command=lambda arg=ds: self._select_cb(arg))
        self.datestr.set(dates[selection].strftime(self.format))


class Window(tk.Tk):
    date_format = "%A %d %B %Y"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.date_select = DateOptionMenu(self, command=self.select_date, width=25)
        self.date_select.pack(padx=10, pady=10)
        self.select_date(datetime.now())

    def select_date(self, date):
        """Change dates to 4 days surounding date."""
        print(date)
        self.date_select.set_dates(
            [date + timedelta(days=days) for days in range(-4, 5)], 4
        )


Window().mainloop()
(Oct-12-2023, 11:01 AM)jacksfrustration Wrote: [ -> ]i want to make a list of days and dates for the current month
(Oct-12-2023, 02:37 PM)jacksfrustration Wrote: [ -> ]Is there a way to ... display the past 5 and upcoming 5 days
these are fairly different requiremets
You can easily generate dates between t-5 and t=5
from datetime import date, timedelta

def dates(offset=5):
    tday = date.today()
    for delta in range(-offset, offset+1):
        yield (tday + timedelta(days=delta)).strftime('%a %d %B %Y')

print(list(dates()))
Here is the code to create a list of dates and dates in the desired format:

Python
import datetime

# Get the current year and month
current_year = datetime.datetime.now().year
current_month = datetime.datetime.now().month

# Create a list to store the formatted dates
formatted_dates = []

# Iterate through each day of the current month
for day in range(1, 32):
try:
# Create a datetime object for the current date
current_date = datetime.date(current_year, current_month, day)

# Format the date as "day_name day_numberth month_name year"
formatted_date = current_date.strftime("%A %dth %B %Y")

# Add the formatted date to the list
formatted_dates.append(formatted_date)
except ValueError:
# If the day is invalid for the current month, skip it
pass

# Now you have the list of formatted dates in formatted_dates
print(formatted_dates)
fnaf
hi regarding the script above, there is a similarity to my question , because am declaring strftime on how to put spaces between the dates as of now I'm making a script that creates a folder based on previous time.

from datetime import datetime, date

oneday = datetime.timedelta(days-1)
yesterday = datetime.date.today() - oneday
path = "G:"
current_time = yesterday.strftime('%Y\%b -&Y\%Y-%m-%d')
command = mkdir {0}".format(current_time)
os.chdir(path)
os.system(command)

the output should create directory
2024
-Jan 2024 <== subfolder of 2024
-2024-01-11<==sobfolder of Jan 2024
Pages: 1 2