A logbook for curious waters
← Software Engineering Field Guide

Introduce Local Extension

Before you begin: Classes, composition, and date arithmetic.

Introduce Local Extension creates a local type that adds useful operations around a library type you do not control. A wrapper stores the library value and supplies the extra behavior. Inheritance is another possibility only when the library type supports safe subclassing. 1

Give a group of date rules one home

Suppose several screens need to identify weekends and advance to the next weekday. Rather than scattering that arithmetic across screens, create a small wrapper around the platform date.

The rule here is specifically Monday through Friday. Holidays, time zones, and working hours are outside its scope.

public sealed class WeekdayDate
{
    public DateOnly Value { get; }
    public WeekdayDate(DateOnly value) { Value = value; }

    public bool IsWeekend
    {
        get
        {
            return Value.DayOfWeek == DayOfWeek.Saturday ||
                   Value.DayOfWeek == DayOfWeek.Sunday;
        }
    }

    public WeekdayDate Next()
    {
        var result = new WeekdayDate(Value.AddDays(1));
        while (result.IsWeekend)
        {
            result = new WeekdayDate(result.Value.AddDays(1));
        }
        return result;
    }
}
var day = new WeekdayDate(new DateOnly(2026, 9, 25));
Console.WriteLine(day.Next().Value); // Monday, September 28

Value retains the platform date. IsWeekend names one rule, and Next reuses it. Calling Next creates a new wrapper rather than modifying day.

from datetime import date, timedelta


class WeekdayDate:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @property
    def is_weekend(self):
        return self._value.weekday() >= 5

    def next(self):
        result = WeekdayDate(self._value + timedelta(days=1))
        while result.is_weekend:
            result = WeekdayDate(result.value + timedelta(days=1))
        return result
day = WeekdayDate(date(2026, 9, 25))
print(day.next().value)  # 2026-09-28

The wrapper retains a date, adds named rules, and returns another wrapper for the next weekday. It does not modify Python’s built-in date implementation.

Decide whether a wrapper is worth carrying

The alternative is ordinary functions accepting dates. With only these two operations, that may be simpler. A wrapper becomes more attractive when a larger, coherent set of operations belongs to a domain-specific date concept.

Callers now distinguish the wrapper from the underlying date and may need to unwrap Value or value when calling a library. Decide how equality, formatting, serialization, and further arithmetic should work rather than assuming they are inherited automatically. This wrapper deliberately does not implement value equality.

Unlike an Adapter, the primary purpose here is to add operations, not to translate an incompatible interface into an existing one. Keep the extension small and explicit; do not accidentally create an incomplete replacement for the standard date library.

Sources

  1. Martin Fowler — Refactoring catalog, for the refactoring vocabulary.
  2. Microsoft — DateOnly and Python — datetime, for the wrapped date behavior.