{"id":1441,"date":"2026-10-22T18:00:00","date_gmt":"2026-10-22T17:00:00","guid":{"rendered":"https:\/\/wade.one\/blog\/?p=1441"},"modified":"2026-10-22T18:00:00","modified_gmt":"2026-10-22T17:00:00","slug":"a-scheduled-job-needs-a-time-zone-not-just-an-hour","status":"publish","type":"post","link":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/","title":{"rendered":"A Scheduled Job Needs a Time Zone, Not Just an Hour"},"content":{"rendered":"<p>&#8220;Run it at six&#8221; is incomplete information for a scheduled job. Six where, and should it stay at six when the clocks change? If the requirement is a local wall-clock time, storing a fixed UTC offset can quietly move the job by an hour for part of the year.<\/p>\n<p>I would record the intended time zone alongside the schedule, then calculate the corresponding UTC instant for each occurrence. PHP&#8217;s <a href=\"https:\/\/www.php.net\/manual\/en\/class.datetimeimmutable.php\">DateTimeImmutable<\/a> supports working with time-zone-aware date objects without changing the original object in place. The important part is preserving the meaning of the schedule, rather than just getting a plausible timestamp into a field.<\/p>\n<p>The awkward cases deserve an explicit decision: a local time that occurs twice when the clocks go back, or does not occur when they go forward. For a recurring task, adding a fixed number of seconds to yesterday&#8217;s execution is not always equivalent to the next local calendar occurrence. Test the dates around a clock change, not only a random Tuesday in the middle of summer.<\/p>\n<p>Time-zone bugs are annoying because the code can be internally consistent and still violate what somebody asked for. A schedule should be readable as a human promise, with a precise instant behind each run. If that promise is &#8220;18:00 in London&#8221;, keep London in the data.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Run it at six&#8221; is incomplete information for a scheduled job.<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[13],"tags":[35,275,274],"class_list":["post-1441","post","type-post","status-publish","format-standard","hentry","category-programming","tag-php","tag-scheduling","tag-time-zones"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one\" \/>\n<meta property=\"og:description\" content=\"&quot;Run it at six&quot; is incomplete information for a scheduled job.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/\" \/>\n<meta property=\"og:site_name\" content=\"wade.one\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-22T17:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1518\" \/>\n\t<meta property=\"og:image:height\" content=\"1506\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:site\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"A Scheduled Job Needs a Time Zone, Not Just an Hour\",\"datePublished\":\"2026-10-22T17:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/\"},\"wordCount\":227,\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"keywords\":[\"php\",\"scheduling\",\"time-zones\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/\",\"name\":\"A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-22T17:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/22\\\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wade.one\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A Scheduled Job Needs a Time Zone, Not Just an Hour\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/\",\"name\":\"wade.one\",\"description\":\"wade womersley - york based software engineer\",\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wade.one\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\",\"name\":\"Wade Womersley\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"contentUrl\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"width\":202,\"height\":200,\"caption\":\"Wade Womersley\"},\"logo\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/","og_locale":"en_GB","og_type":"article","og_title":"A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one","og_description":"\"Run it at six\" is incomplete information for a scheduled job.","og_url":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/","og_site_name":"wade.one","article_published_time":"2026-10-22T17:00:00+00:00","og_image":[{"width":1518,"height":1506,"url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_creator":"@wadewomersley","twitter_site":"@wadewomersley","twitter_misc":{"Estimated reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/#article","isPartOf":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/"},"author":{"name":"","@id":""},"headline":"A Scheduled Job Needs a Time Zone, Not Just an Hour","datePublished":"2026-10-22T17:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/"},"wordCount":227,"publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"keywords":["php","scheduling","time-zones"],"articleSection":["Programming"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/","url":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/","name":"A Scheduled Job Needs a Time Zone, Not Just an Hour - wade.one","isPartOf":{"@id":"https:\/\/wade.one\/blog\/#website"},"datePublished":"2026-10-22T17:00:00+00:00","breadcrumb":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/wade.one\/blog\/2026\/10\/22\/a-scheduled-job-needs-a-time-zone-not-just-an-hour\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wade.one\/blog\/"},{"@type":"ListItem","position":2,"name":"A Scheduled Job Needs a Time Zone, Not Just an Hour"}]},{"@type":"WebSite","@id":"https:\/\/wade.one\/blog\/#website","url":"https:\/\/wade.one\/blog\/","name":"wade.one","description":"wade womersley - york based software engineer","publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wade.one\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":["Person","Organization"],"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3","name":"Wade Womersley","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","contentUrl":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","width":202,"height":200,"caption":"Wade Womersley"},"logo":{"@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png"}}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1298,"url":"https:\/\/wade.one\/blog\/2026\/05\/10\/php-8-5-clone-with-makes-value-objects-less-annoying\/","url_meta":{"origin":1441,"position":0},"title":"PHP 8.5 Clone With Makes Value Objects Less Annoying","author":"","date":"May 10, 2026","format":false,"excerpt":"PHP 8.5's clone-with syntax makes immutable value objects easier to work with, especially around readonly properties.","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1109,"url":"https:\/\/wade.one\/blog\/2023\/03\/26\/php-8-2-vs-7-4\/","url_meta":{"origin":1441,"position":1},"title":"PHP 8.2 vs 7.4","author":"Wade","date":"March 26, 2023","format":false,"excerpt":"PHP is a widely used programming language that has been evolving rapidly in recent years. PHP 8.2 is the latest release, which came out on November 25th, 2021. This version brings several improvements, new features, and bug fixes, making it more efficient and secure than PHP 7.4. In this blog\u2026","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":410,"url":"https:\/\/wade.one\/blog\/2010\/01\/07\/snowy-britain-nasa-terra-image\/","url_meta":{"origin":1441,"position":2},"title":"Snowy Britain &#8211; NASA Terra image","author":"Wade","date":"January 7, 2010","format":false,"excerpt":"NASA uploaded an image today of Great Britain from space as of 11:50 UTC today, it's a truly remarkable picture showing just how much it has snowed here. For anyone not from the UK, snow like this has not hit Britain for over 30 years, hence all the hoo-haa about.\u2026","rel":"","context":"In &quot;News&quot;","block_context":{"text":"News","link":"https:\/\/wade.one\/blog\/category\/news\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2016\/04\/GreatBritain.A2010007.1150.1km.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2016\/04\/GreatBritain.A2010007.1150.1km.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2016\/04\/GreatBritain.A2010007.1150.1km.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/wade.one\/blog\/wp-content\/uploads\/2016\/04\/GreatBritain.A2010007.1150.1km.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1299,"url":"https:\/\/wade.one\/blog\/2026\/05\/11\/php-8-5-nodiscard-is-a-small-api-safety-feature\/","url_meta":{"origin":1441,"position":3},"title":"PHP 8.5 NoDiscard Is a Small API Safety Feature","author":"Wade","date":"May 11, 2026","format":false,"excerpt":"PHP 8.5's NoDiscard attribute gives library and application code a direct way to say that ignoring a return value is probably a bug.","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1328,"url":"https:\/\/wade.one\/blog\/2026\/05\/31\/php-8-5-array-first-and-array-last-remove-tiny-annoying-helpers\/","url_meta":{"origin":1441,"position":4},"title":"PHP 8.5 array_first and array_last Remove Tiny Annoying Helpers","author":"","date":"May 31, 2026","format":false,"excerpt":"PHP 8.5's array_first and array_last are small additions, but they remove helper functions most PHP codebases already reinvent.","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1296,"url":"https:\/\/wade.one\/blog\/2026\/05\/08\/php-8-5s-uri-extension-fixes-a-real-web-problem\/","url_meta":{"origin":1441,"position":5},"title":"PHP 8.5&#8217;s URI Extension Fixes a Real Web Problem","author":"","date":"May 8, 2026","format":false,"excerpt":"PHP 8.5's new URI extension is not flashy, but it gives PHP a better built-in answer for parsing modern URLs.","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1441","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/comments?post=1441"}],"version-history":[{"count":1,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1441\/revisions"}],"predecessor-version":[{"id":1464,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1441\/revisions\/1464"}],"wp:attachment":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/media?parent=1441"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/categories?post=1441"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/tags?post=1441"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}