---
title: "The Weekend Is Not a Constant"
description: "Why 'is this a working day?' breaks so much software: weekends that differ by country and change over time, holidays that follow the moon, time zones that disagree about today, and the habits that kept my own date logic honest while building HolidayOps."
author: "Syed Ahmer Shah"
date: 2026-10-18
url: https://ahmershah.dev/blogs/the-weekend-is-not-a-constant
tags: ["holidayops", "dates", "time-zones", "python", "backend", "software-design", "engineering-logs"]
series: "The Engineering Logs" (part 16)
---

# The Weekend Is Not a Constant

_Five assumptions about dates that quietly break payroll, scheduling and delivery software, and what I do instead_

![Syed Ahmer Shah waiting at an airport gate with a suitcase as a plane takes off, beside the title The Weekend Is Not a Constant](https://ahmershah.dev/blog/the-weekend-is-not-a-constant/cover-6adbec80.webp)


Somewhere in most codebases there is a line that looks like this:

```python
is_working_day = day.weekday() < 5
```

It reads as obviously true. Monday to Friday, work. Saturday and Sunday, rest. I have written that line myself, more than once, and I meant it every time.

Then I spent a month building [HolidayOps](/blogs/holidayops-case-study-working-days-api), an API whose whole job is answering "is this a working day?" for 250 countries, and that line turned out to be wrong in five separate ways. None of them are exotic. All of them have cost someone a late payment, a missed delivery or a meeting nobody could attend.

Here are the five, and what I do now instead.

* * *

## 1. Everyone rests on Saturday and Sunday

Most of the world does. Not all of it.

When I counted across every country the holidays library supports, 222 rest on Saturday and Sunday. Eighteen rest on Friday and Saturday, including Saudi Arabia, Egypt and Qatar. Eight rest on Sunday only. Iran rests on Friday alone. Brunei takes Friday and Sunday off and works the Saturday in between.

That `weekday() < 5` line marks a Sunday in Riyadh as a day off, when it's the first day of the working week, and a Friday as a working day, when the office is closed.

**What I do instead:** the weekend is data, looked up per country. Never a constant in the code, never a default that a country can forget to override.

## 2. A country's weekend never changes

This one surprised me more than the first.

The United Arab Emirates moved its weekend from Friday-Saturday to Saturday-Sunday at the start of 2022. Other countries have made similar moves over the years. If your system stores one weekend per country, it gets every date before the change wrong, and the work that cares most about working days, payroll, leave balances, contract deadlines and settlements, is exactly the work that looks back at old dates.

**What I do instead:** ask for the weekend *per date*, not per country. In HolidayOps the domain layer asks the library whether a specific date falls on that country's weekend, and the library knows when the rule changed. The answer for 3 January 2021 and 3 January 2022 can differ, and should.

## 3. Holidays are known in advance

Some are. Many aren't, not exactly.

Holidays that follow the lunar calendar move by about eleven days every year, and their exact date can depend on the sighting of the moon. Governments also add days at short notice: a national celebration, a period of mourning, an extra day joined to a long weekend.

You can't solve that with a better algorithm. You can only be honest about it. HolidayOps takes its data from the open-source holidays library, which is updated several times a year by people who follow these announcements far more closely than I can. The terms of service say plainly that for dates with legal or financial weight, you should check the official source as well.

**What I do instead:** treat holiday data as something that changes. Pin the library to an exact version, upgrade it on purpose, and cache holiday lists under a key that includes that version, so an upgrade can never serve stale dates.

## 4. A working day is either on or off

Real calendars have more states than that.

Some countries move a working day onto the weekend to bridge a holiday, so a Saturday becomes a working day and the Friday before it becomes a day off. Companies run half days before a festival. They close for a week the government never declared. A team can choose to work a Saturday at the end of a quarter.

If the only state your code knows is a boolean, every one of those becomes a special case somebody has to remember.

**What I do instead:** every answer carries a reason, not just a yes or a no. HolidayOps answers with one of a short list: a normal working day, the weekend, a public holiday, a weekend day moved to a working day, a company closure, a half day or an extra working day. Half days count as working days in the maths, because that's how payroll treats them, but they are flagged so a scheduler can still avoid them. The reason is what lets a person trust the answer, because they can see why.

## 5. Everyone agrees what today is

They don't, and this one bit me in my own product.

At 2 a.m. in Dubai it is still yesterday in New York. "Is today a working day?" has no single answer for a team that spans both. My first landing page computed today in UTC, which meant that for the first five hours of every day, it showed yesterday to the people it was mostly built for.

Then the cache made it worse. The page was cached for six hours, so just after midnight it could keep showing the old "today" until the cache expired. Nothing failed loudly; it was simply, quietly wrong.

**What I do instead:** "today" is always *someone's* today. Each country is read in its own time zone. Where a country spans several, I use the capital's, because the standard data lists zones alphabetically and would otherwise start the United States in Adak, Alaska. Anything cached that mentions today carries the hour in its key, because somewhere a new day starts every hour.

* * *

## The habit underneath all five

Every one of these bugs came from the same place: date logic written in more than one spot.

A helper in the API, a slightly different one in the email job, a third in the frontend. Each looked correct on its own. They just didn't agree with each other, and when two parts of a product disagree about a date, the person reading both stops trusting either.

So in HolidayOps there is exactly one place that knows what a working day is. It's a small package of plain Python with no web framework imports, it has full branch coverage, and everything else calls it: the API, the calendar feeds, the webhooks, the monthly email and the public pages. When I fix a date bug, I fix it once, and every surface gets the fix at the same time.

If you take one thing from this, take that. Not a library, not a pattern. Just a rule: **one place decides what day it is.**

The rest of the build, the architecture, the security and the mistakes, is in the [HolidayOps case study](/blogs/holidayops-case-study-working-days-api).


---

*Originally published at https://ahmershah.dev/blogs/the-weekend-is-not-a-constant — © Syed Ahmer Shah*
