日本語 · English

Patch Tuesday: the second Tuesday at 10:00 Pacific, shown in any time zone

Translated from the canonical Japanese page recipes/patch-tuesday.md.

Microsoft publishes its monthly security update on the second Tuesday of each month, typically at 10:00 AM Pacific Time (PST/PDT) (Microsoft Learn: Update release cycle for Windows clients; the fourth Tuesday carries the optional preview release, out-of-band updates ship as needed). It is one instant for the whole world, yet on local calendars both the date and the time move — Pacific Time observes daylight saving. In Japan it lands on Wednesday at 2 or 3 am; in London on Tuesday at 18:00 (17:00 in March only); in Sydney on Wednesday between 3 and 5 am.

Whether and when an update ships is Microsoft’s call, announced by Microsoft. This page covers one thing: producing the scheduled points, in any time zone, from a single definition.

What happens with the tools you already have

Writing it in Kairos

One definition, in Pacific Time. The time of day is attached with at (the wall-clock 10:00 survives the daylight-saving switches):

# eval: 2026-01-01..2027-01-01 tz: America/Los_Angeles
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
patchDay = everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(2)
patchDay |> at(T10:00)
#=> 2026-01-13T10:00 2026-02-10T10:00 2026-03-10T10:00 2026-04-14T10:00 2026-05-12T10:00 2026-06-09T10:00
#=> 2026-07-14T10:00 2026-08-11T10:00 2026-09-08T10:00 2026-10-13T10:00 2026-11-10T10:00 2026-12-08T10:00

The same definition, shown in Tokyo. The tz: in # eval: is the display zone — the definition does not change by a single character (--tz Asia/Tokyo in the CLI, or the display-zone switch in the Playground):

# eval: 2026-01-01..2027-01-01 tz: Asia/Tokyo
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
patchDay = everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(2)
patchDay |> at(T10:00)
#=> 2026-01-14T03:00 2026-02-11T03:00 2026-03-11T02:00 2026-04-15T02:00 2026-05-13T02:00 2026-06-10T02:00
#=> 2026-07-15T02:00 2026-08-12T02:00 2026-09-09T02:00 2026-10-14T02:00 2026-11-11T03:00 2026-12-09T03:00

3 am in January, February, November and December; 2 am from March to October. The date is always a Wednesday, but in April and July it is the third Wednesday — those months start on a Wednesday, so the day after the second Tuesday (the 14th) is the month’s third Wednesday. “Second Wednesday” and “second Tuesday” do not name the same point.

London sees Tuesday 18:00, and 17:00 in March only (the US switches to daylight saving three weeks before the UK):

# eval: 2026-01-01..2027-01-01 tz: Europe/London
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
patchDay = everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(2)
patchDay |> at(T10:00)
#=> 2026-01-13T18:00 2026-02-10T18:00 2026-03-10T17:00 2026-04-14T18:00 2026-05-12T18:00 2026-06-09T18:00
#=> 2026-07-14T18:00 2026-08-11T18:00 2026-09-08T18:00 2026-10-13T18:00 2026-11-10T18:00 2026-12-08T18:00

Sydney, with the southern hemisphere’s daylight saving running the other way, sees three different hours (5, 4 and 3 am):

# eval: 2026-01-01..2027-01-01 tz: Australia/Sydney
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
patchDay = everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(2)
patchDay |> at(T10:00)
#=> 2026-01-14T05:00 2026-02-11T05:00 2026-03-11T04:00 2026-04-15T03:00 2026-05-13T03:00 2026-06-10T03:00
#=> 2026-07-15T03:00 2026-08-12T03:00 2026-09-09T03:00 2026-10-14T04:00 2026-11-11T05:00 2026-12-09T05:00

The wrong one — “second Wednesday, 3 am, in Tokyo”. Rewritten under a Tokyo premise, the list agrees with the correct one only in January, February, November and December (an hour off from March to October, a week off in April and July):

# eval: 2026-01-01..2027-01-01 tz: Asia/Tokyo
premise Tokyo {
  calendar-system: Gregorian
  tz: "Asia/Tokyo"
  wkst: Mon
}
@Tokyo
everyDay |> filter(d => weekday(d) == Wed) |> within(month) |> nth(2) |> at(T03:00)
#=> 2026-01-14T03:00 2026-02-11T03:00 2026-03-11T03:00 2026-04-08T03:00 2026-05-13T03:00 2026-06-10T03:00
#=> 2026-07-08T03:00 2026-08-12T03:00 2026-09-09T03:00 2026-10-14T03:00 2026-11-11T03:00 2026-12-09T03:00

What follows the release is a relative date. Staged rollouts (dev → test → production) are defined relative to the release day. “Production on the second Saturday at 22:00 Pacific” is the release-day set shifted by four days with a time attached:

# eval: 2026-01-01..2027-01-01 tz: America/Los_Angeles
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
patchDay = everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(2)
patchDay |> shift(+4, unit: day) |> at(T22:00)
#=> 2026-01-17T22:00 2026-02-14T22:00 2026-03-14T22:00 2026-04-18T22:00 2026-05-16T22:00 2026-06-13T22:00
#=> 2026-07-18T22:00 2026-08-15T22:00 2026-09-12T22:00 2026-10-17T22:00 2026-11-14T22:00 2026-12-12T22:00

The fourth-Tuesday preview release is the same shape with nth(4):

# eval: 2026-01-01..2027-01-01 tz: America/Los_Angeles
premise PT {
  calendar-system: Gregorian
  tz: "America/Los_Angeles"
  wkst: Sun
}
@PT
everyDay |> filter(d => weekday(d) == Tue) |> within(month) |> nth(4) |> at(T10:00)
#=> 2026-01-27T10:00 2026-02-24T10:00 2026-03-24T10:00 2026-04-28T10:00 2026-05-26T10:00 2026-06-23T10:00
#=> 2026-07-28T10:00 2026-08-25T10:00 2026-09-22T10:00 2026-10-27T10:00 2026-11-24T10:00 2026-12-22T10:00

Scope

Try it in your browser

The same definition, with only the display zone changed (the Playground’s display-zone switch does the same):

Pacific (the definition as is) · shown in Tokyo · shown in London · shown in Sydney · the wrong one (second Wednesday, 3 am Tokyo) · production (second Saturday, 22:00) · preview (fourth Tuesday)

— move from/to, change at(T10:00), and see what happens. Everything runs in the browser; nothing is sent anywhere.