Standard Library Tools: Dates Revisited
Learning Objectives
- You can create
datevalues from ISO date strings. - You can convert
datevalues back into strings with.isoformat(). - You can use
timedeltafor date windows. - You can explain why date strings should be parsed before date arithmetic.
The study log stores dates because summaries become much more useful when time is involved. A string such as "2026-05-10" is fine for storage, but it is not the best value for date arithmetic. For arithmetic, comparisons, and date windows, use datetime.date.
from datetime import date
session_day = date.fromisoformat("2026-05-10")print(session_day)print(type(session_day))date.fromisoformat(...) parses a string in YYYY-MM-DD format and returns a date object. Once the value is a real date, Python understands date operations.
Parse ISO date
0 / 5 points
What does date.fromisoformat("2026-05-10") return?
Back to Text
Files usually store text. When you need to write a date value back into JSON or CSV, convert it to a string:
from datetime import date
today = date.today()text = today.isoformat()print(text)The .isoformat() method returns a string such as "2026-06-11". This format is useful because it is unambiguous, common, and sorts in chronological order when the strings are consistently formatted.
The boundary is a good rule of thumb:
- Inside the program, use
dateobjects when doing date logic. - At the file boundary, use ISO strings because JSON and CSV store text naturally.
Date boundary
0 / 5 points
Why does the course store dates as ISO strings in files but convert them to date values for logic?
Why ISO Format Is Useful
The format YYYY-MM-DD has a practical advantage: it sorts correctly as text when every date uses the same format.
dates = ["2026-05-12", "2026-05-09", "2026-06-01"]print(sorted(dates))This produces chronological order. That is not true for many other human date formats. For example, "12/05/2026" can mean different things in different countries, and text sorting month-first or day-first dates can produce surprising orderings.
This does not mean ISO strings are a replacement for date objects. They are good for storage and display. When you subtract dates, create date windows, or compare with today’s date, parse them.
Date Differences
Subtracting two date values gives a timedelta:
from datetime import date
today = date.fromisoformat("2026-05-15")session_day = date.fromisoformat("2026-05-10")gap = today - session_day
print(gap.days)This prints 5. The .days attribute gives the number of days in the difference.
This is safer than trying to subtract pieces of a string. The difference between May 31 and June 1 is one day, but subtracting the day numbers gives 1 - 31, which is nonsense. Date libraries exist because dates have rules.
Days since a session
0 / 10 points
Define a function named days_since(session_date_text, today_text).
Both parameters are ISO date strings in YYYY-MM-DD format. Return the number of days from the session date to today.
Example: days_since("2026-05-10", "2026-05-15") should return 5.
Import with from datetime import date and use date.fromisoformat(...). Do not use string subtraction or manual month arithmetic.
Do not ask for user input and do not print inside the function.
Date Windows
A timedelta represents a duration. You can subtract one from a date:
from datetime import date, timedelta
today = date.fromisoformat("2026-05-15")start = today - timedelta(days=6)
print(start)If today is May 15, then the seven-day window including today starts on May 9: May 9, 10, 11, 12, 13, 14, 15.
That inclusive window appears often:
def in_last_seven_days(day, today): start = today - timedelta(days=6) return start <= day <= todayThe comparison reads almost like English: start is less than or equal to the day, and the day is less than or equal to today.
Seven-day date window
0 / 5 points
Arrange the lines into a helper that returns whether day_text is in the seven-day window ending on today_text.
Applying This to Session Records
The study log from Structuring Your Data stores JSON records shaped like this on disk:
{"subject": "math", "minutes": 45, "date": "2026-05-10"}Inside that class-based program, those records are rebuilt as Session objects. The same three fields are still there, but you read them with attributes such as session.date and session.minutes.
The date field is still a string. A function that needs date logic should parse it at the point where it needs the date:
from datetime import date, timedelta
def count_recent_sessions(sessions, today_text): today = date.fromisoformat(today_text) start = today - timedelta(days=6)
count = 0 for session in sessions: day = date.fromisoformat(session.date) if start <= day <= today: count += 1 return countThis function takes today_text as a parameter instead of calling date.today() itself. That makes it deterministic in tests: the answer does not change just because the calendar changed overnight.
Total recent minutes
0 / 10 points
Define a function named total_recent_minutes(sessions, today_text).
sessions is a list of dictionaries. Each dictionary has a date key containing an ISO date string and a numeric minutes key.
The chapter builds a similar helper for Session objects and reads values with session.date and session.minutes. The grader passes plain dictionaries instead, so read values with session["date"] and session["minutes"].
Return the sum of the minutes from sessions in the seven-day window ending on today_text, including both the start date and today. Sessions outside the window must not affect the total.
Example: if today is 2026-05-15, the window is 2026-05-09 through 2026-05-15.
For example, if the window contains sessions of 30 and 45 minutes, return 75. If sessions is empty or no sessions fall in the window, return 0. Do not ask for user input and do not print inside the function.
Invalid Dates
date.fromisoformat(...) can fail:
from datetime import date
date.fromisoformat("2026-02-30") # ValueErrordate.fromisoformat("May 10") # ValueErrorThat is good. February 30 is not a real date, and "May 10" is not the format the project expects.
Where should this error be handled? Usually at the boundary where external data enters the program. In Reading and Writing Files and Structuring Your Data, the loader is responsible for deciding whether a saved row or record is valid enough to enter the program. Once a session has been loaded successfully, summary functions should be able to assume that its date string is parseable.
This is the same boundary idea as before:
- loaders are defensive because files may contain bad data,
- summary helpers are simpler because they receive already-validated data,
- tests can focus on each responsibility separately.
If a summary helper catches every possible bad date itself, the code becomes noisy and the real data-quality decision is spread everywhere. Prefer one clear boundary.
Check Your Understanding
- What does
date.fromisoformat("2026-05-10")return? - Why should a program convert a
dateback to text before writing JSON? - Why is
todayoften a parameter in date-related helper functions? - What does
start <= day <= todaymean?
AI Study Aid
Create a chapter diagram
We're looking into to what extent AI-generated diagrams could help with studying.
Use this study aid to generate an AI-generated visual summary of the material you just studied.
Each diagram style emphasizes the content in a different way, so you can choose the focus
that feels most useful.
Using the diagram generator is voluntary and does not affect your course progress. We encourage
you to try it out and see if it helps, but it's totally up to you! Your answers help us understand
how to make better study aids in the future.