Date Utilities Example — days_from_epoch, date_from_days, day_of_week

This example exercises three calendar utility functions:

Ten notable historical dates are converted to day counts, round-tripped back to dates to verify correctness, and their day of the week is printed. A calendar grid for January 2024 is rendered using day_of_week to determine the starting column.

Example Code

"""IMSL date utility example: days_from_epoch, date_from_days, day_of_week.

Outputs:
- Tables printed to stdout
- SVG timeline bar chart saved to test_output/example_imsl_date_utils.svg
"""
from __future__ import annotations

from pathlib import Path
from typing import Dict, List, Tuple

import matplotlib.pyplot as plt
import numpy as np

from utilities import days_from_epoch, date_from_days, day_of_week

# Day-of-week names (Python weekday(): 0=Monday … 6=Sunday)
_DOW_NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

# Ten notable dates (label, year, month, day)
_NOTABLE_DATES: List[Tuple[str, int, int, int]] = [
    ("Epoch (1900-01-01)",     1900,  1,  1),
    ("Wright Brothers (1903)", 1903, 12, 17),
    ("WWII end (1945-09-02)",  1945,  9,  2),
    ("Moon landing (1969)",    1969,  7, 20),
    ("IBM PC (1981-08-12)",    1981,  8, 12),
    ("WWW invented (1991)",    1991,  8,  6),
    ("Y2K (2000-01-01)",       2000,  1,  1),
    ("iPhone launch (2007)",   2007,  6, 29),
    ("New Year 2024",          2024,  1,  1),
    ("Today ref (2025-01-01)", 2025,  1,  1),
]


def run_demo_imsl_date_utils() -> Dict[str, object]:
    """Demonstrate date utility functions from the utilities library.

    Converts a list of notable historical dates to integer day counts from
    the Jan 1 1900 epoch, converts them back to verify round-trips, and
    finds the day of the week for each date.  Also renders a simple calendar
    grid for January 2024 using ``day_of_week``.

    Args:
        None

    Returns:
        Dict[str, object]: Result dict with keys ``labels``, ``day_counts``,
            ``round_trip_ok``, ``dow_names``, and ``plot_path``.
    """
    labels: List[str] = []
    day_counts: List[int] = []
    dow_names: List[str] = []
    round_trip_ok: List[bool] = []

    print("\nIMSL Date Utilities Example")
    print("=" * 70)
    print(
        f"\n{'Date label':<30} {'Days from epoch':>16} "
        f"{'Round-trip':>14} {'Day of week':<12}"
    )
    print("-" * 75)

    for label, yr, mo, dy in _NOTABLE_DATES:
        n = days_from_epoch(yr, mo, dy)
        yr2, mo2, dy2 = date_from_days(n)
        ok = (yr2 == yr) and (mo2 == mo) and (dy2 == dy)
        dow_idx = day_of_week(yr, mo, dy)
        dow = _DOW_NAMES[dow_idx]

        labels.append(label)
        day_counts.append(n)
        round_trip_ok.append(ok)
        dow_names.append(dow)

        status = "✓" if ok else "✗"
        print(
            f"{label:<30} {n:>16,} "
            f"{status:>14}  {dow:<12}"
        )

    print("-" * 75)
    all_ok = all(round_trip_ok)
    print(f"\nAll round-trips correct: {all_ok}")

    # ── Calendar grid for January 2024 ────────────────────────────────────────
    print("\n--- January 2024 Calendar ---")
    print(f"{'Mo':>4} {'Tu':>4} {'We':>4} {'Th':>4} {'Fr':>4} {'Sa':>4} {'Su':>4}")
    first_dow = day_of_week(2024, 1, 1)  # 0=Mon … 6=Sun
    row: List[str] = ["  "] * first_dow
    for d in range(1, 32):
        row.append(f"{d:2d}")
        if len(row) == 7:
            print("  ".join(f"{v:>2}" for v in row))
            row = []
    if row:
        row.extend(["  "] * (7 - len(row)))
        print("  ".join(f"{v:>2}" for v in row))

    # ── Specific dates / epoch edge-case ─────────────────────────────────────
    epoch_days = days_from_epoch(1900, 1, 1)
    print(f"\nEpoch check: days_from_epoch(1900,1,1) = {epoch_days}  (expected 0)")

    millennium = days_from_epoch(2000, 1, 1)
    print(f"Y2K:         days_from_epoch(2000,1,1) = {millennium:,}")
    yr_back, mo_back, dy_back = date_from_days(millennium)
    print(f"Back:        date_from_days({millennium}) = {yr_back}-{mo_back:02d}-{dy_back:02d}")

    # ── Plot ──────────────────────────────────────────────────────────────────
    output_dir = Path("test_output")
    output_dir.mkdir(parents=True, exist_ok=True)
    plot_path = output_dir / "example_imsl_date_utils.svg"

    fig, ax = plt.subplots(figsize=(13, 6))

    y_pos = np.arange(len(labels))
    counts_arr = np.array(day_counts)

    colors = plt.colormaps["tab10"](np.linspace(0, 1, len(labels)))
    bars = ax.barh(y_pos, counts_arr, color=colors, alpha=0.85)

    for bar, count in zip(bars, counts_arr):
        ax.text(
            count + counts_arr.max() * 0.01,
            bar.get_y() + bar.get_height() / 2,
            f"{count:,}",
            va="center",
            fontsize=8,
        )

    ax.set_yticks(y_pos)
    ax.set_yticklabels(labels, fontsize=9)
    ax.set_xlabel("Days from epoch (Jan 1, 1900)")
    ax.set_title("days_from_epoch — Notable historical dates", fontweight="bold")
    ax.grid(True, axis="x", alpha=0.3)
    ax.invert_yaxis()

    fig.tight_layout()
    fig.savefig(plot_path, format="svg")
    plt.close(fig)

    print(f"\nPlot saved to: {plot_path}")

    return {
        "labels": labels,
        "day_counts": day_counts,
        "round_trip_ok": round_trip_ok,
        "dow_names": dow_names,
        "plot_path": str(plot_path),
    }


if __name__ == "__main__":
    run_demo_imsl_date_utils()

Plot Output

Horizontal bar chart showing days-from-epoch for ten notable historical dates

Horizontal timeline bar chart for ten historical dates. Bar length represents the number of days elapsed since Jan 1, 1900.

Console Output

IMSL Date Utilities Example
======================================================================

Date label                      Days from epoch     Round-trip Day of week 
---------------------------------------------------------------------------
Epoch (1900-01-01)                            0              Γ£ô  Monday      
Wright Brothers (1903)                    1,445              Γ£ô  Thursday    
WWII end (1945-09-02)                    16,680              Γ£ô  Sunday      
Moon landing (1969)                      25,402              Γ£ô  Sunday      
IBM PC (1981-08-12)                      29,808              Γ£ô  Wednesday   
WWW invented (1991)                      33,454              Γ£ô  Tuesday     
Y2K (2000-01-01)                         36,524              Γ£ô  Saturday    
iPhone launch (2007)                     39,260              Γ£ô  Friday      
New Year 2024                            45,290              Γ£ô  Monday      
Today ref (2025-01-01)                   45,656              Γ£ô  Wednesday   
---------------------------------------------------------------------------

All round-trips correct: True

--- January 2024 Calendar ---
  Mo   Tu   We   Th   Fr   Sa   Su
 1   2   3   4   5   6   7
 8   9  10  11  12  13  14
15  16  17  18  19  20  21
22  23  24  25  26  27  28
29  30  31                

Epoch check: days_from_epoch(1900,1,1) = 0  (expected 0)
Y2K:         days_from_epoch(2000,1,1) = 36,524
Back:        date_from_days(36524) = 2000-01-01

Plot saved to: test_output\example_imsl_date_utils.svg