{
  "description": "Recent content for Nathan Grigg",
  "feed_url": "https://nathangrigg.com/feed.json",
  "home_page_url": "https://nathangrigg.com/",
  "icon": "https://nathangrigg.com/favicon.png",
  "items": [
    {
      "content_html": "<p>If you want to feel emotions and human connection, take your kid to the DMV drive test and chill with the family members of the other testers while your loved ones are out on their drives.</p>\n",
      "date_published": "2026-07-28T09:42:59-07:00",
      "id": "https://nathangrigg.com/2026/07/dqzsfc/",
      "url": "https://nathangrigg.com/2026/07/dqzsfc/"
    },
    {
      "content_html": "<p>In yesterday&rsquo;s post about <a href=\"https://nathangrigg.com/2026/07/usa-sunrise-times/\">sunrises</a>, I made a snarky offhand comment about\ncertain places being in the wrong time zone.</p>\n<p>Today I drew a map that highlights the locations that are more than 7.5 degrees\nfrom the central longitude of their time zone. (US time zones are spaced every\nhour, which corresponds to 15 degrees of longitude.)</p>\n<figure class=\"center\"><img src=\"/2026/07/us-time-zone-alignment/map.png\" class=\"center\"\n    alt=\"Map of the USA with the centers of each time zone marked and locations that are farther than 30 minutes away from the center shaded.\">\n</figure>\n\n<p>If you are in the correct time zone, then your average solar noon is between\n11:30 a.m. (if you live on the far eastern edge) and 12:30 p.m. (on the far\nwestern edge) Standard Time.</p>\n<p>A few states and parts of several others are clinging to the Eastern Time\nZone when they should join Central. The Great Plains states and Western Texas\nshould really join Mountain Time. My birth state of Idaho should observe\nPacific Time.</p>\n<p>Instead, these locations are all running 30-60 minutes later than they should\nbe. And of course, if we do end up switching to full-time Daylight Saving Time,\nthat will become 90-120 minutes, which seems pretty ridiculous to me.</p>\n<p>Then again, they already spend two-thirds of the year in that condition, so\nthis misalignment isn&rsquo;t exactly new.</p>\n<p>(You may notice that a tiny sliver of Maine is actually too far east for the\nEastern Time Zone, but that one seems like not a big deal.)</p>\n",
      "date_published": "2026-07-18T18:45:36-07:00",
      "id": "https://nathangrigg.com/2026/07/us-time-zone-alignment/",
      "title": "Misaligned Time Zones",
      "url": "https://nathangrigg.com/2026/07/us-time-zone-alignment/"
    },
    {
      "content_html": "<p>Inspired by Dr. Drang&rsquo;s plots <a href=\"https://leancrew.com/all-this/2026/07/permanent-daylight-saving-time/\">illustrating the potential effects in\nChicago</a> of a move to permanent Daylight Saving Time in the US, I wanted to\ninvestigate which places would have the hardest time in the dead of winter.</p>\n<p>I ended up with this map of the USA Lower 48, with regions shaded by the\nlatest sunrise time that occurred between January 1 and January 15,\n2026.</p>\n<p>If any location were to switch to permanent DST, their latest sunrise would be\nan hour later than shown in this map.</p>\n<figure class=\"center\"><img src=\"/2026/07/usa-sunrise-times/sunrise.png\" class=\"center\"\n    alt=\"Map of the contiguous USA with latest sunrise times\">\n</figure>\n\n<p>I have very little sympathy for the orange and red zones, which currently see\ntheir latest sunrise after 8:00 and would move to a post-9:00 sunrise. Parts of Washington,\nMontana, and Michigan are very far north and there is only so much we can do to help.\nIn all other cases, you are in the wrong time zone anyway; this one is on you.</p>\n<p>I do feel for the green areas, which are properly situated but would have to suffer\nthrough at least a few sunrises between 8:30 and 9:00.</p>\n<p>Of course, I think it is silly to use permanent DST rather than permanent\nStandard Time. Sure, a lot of our habits have been built up around astronomical\nnoon being closer to 1 p.m. for most of the year, but I&rsquo;m sure we would figure\nit out quickly enough.</p>\n<p>I&rsquo;ll be fine either way, since I&rsquo;m right on the boundary between dark and light\nblue. I would survive shifting our worst-case winter 7:00 sunrise to 8:00.</p>\n<p>Note that, ignoring DST, the latest sunrise is typically <a href=\"https://aa.usno.navy.mil/faq/rs_solstices\">in January</a> rather\nthan at the winter solstice. But also in some southern areas (including where I\nlive), the seasonal variation in sunrises is small enough that the latest\nsunrise time is actually in March or November, right after the shift to DST or\nbefore the shift back to Standard Time.</p>\n<p>I&rsquo;m not going to post the Python code I used for this because it was\nAI-assisted and sloppily thrown together. I used\n<a href=\"https://geopandas.org/en/stable/\">geopandas</a> to read <a href=\"https://github.com/nvkelso/natural-earth-vector\">Natural\nEarth</a> time zone data (both\nAI choices), and <a href=\"https://rhodesmill.org/skyfield/\">skyfield</a> based on\nmy previous experience with astronomical calculations. I used\n<a href=\"https://scipy.org\">scipy</a> to solve for the boundary points\nand then shaded the regions using <a href=\"https://matplotlib.org\">matplotlib</a>.</p>\n",
      "date_published": "2026-07-17T17:37:46-07:00",
      "id": "https://nathangrigg.com/2026/07/usa-sunrise-times/",
      "title": "Worst case sunrise times in the USA",
      "url": "https://nathangrigg.com/2026/07/usa-sunrise-times/"
    },
    {
      "content_html": "<p>Earlier this week, I put together a quick Jupyter notebook to figure out who\nplays which third-place team in the Round of 32.</p>\n<p>I parsed the Wikipedia table into a Pandas DataFrame with 20 columns:</p>\n<ul>\n<li>\n<p>Twelve columns named <code>'A'</code> through <code>'L'</code> with values <code>True</code> or <code>False</code>,\nindicating that the third-place team from that group qualified for the Round\nof 32.</p>\n</li>\n<li>\n<p>Eight columns named <code>'vA'</code>, <code>'vB'</code>, etc., for the eight first place teams\nthat are slated to play a third-place finisher. The value of these columns is\n<code>3A</code>, <code>3B</code>, etc., for the matchup that will result for the set of third place\nfinishers determined by the values of the first eight columns.</p>\n</li>\n</ul>\n<p>For example, this is the row of the table assuming that the third place\nfinishers from groups A, C, H, and K fail to advance (with True/False shortened\nto T/F for brevity):</p>\n<table>\n\t<thead>\n\t\t\t<tr>\n\t\t\t\t\t<th style=\"text-align: left\">A</th>\n\t\t\t\t\t<th style=\"text-align: left\">B</th>\n\t\t\t\t\t<th style=\"text-align: left\">C</th>\n\t\t\t\t\t<th style=\"text-align: left\">D</th>\n\t\t\t\t\t<th style=\"text-align: left\">E</th>\n\t\t\t\t\t<th style=\"text-align: left\">F</th>\n\t\t\t\t\t<th style=\"text-align: left\">G</th>\n\t\t\t\t\t<th style=\"text-align: left\">H</th>\n\t\t\t\t\t<th style=\"text-align: left\">I</th>\n\t\t\t\t\t<th style=\"text-align: left\">J</th>\n\t\t\t\t\t<th style=\"text-align: left\">K</th>\n\t\t\t\t\t<th style=\"text-align: left\">L</th>\n\t\t\t\t\t<th style=\"text-align: left\">vA</th>\n\t\t\t\t\t<th style=\"text-align: left\">vB</th>\n\t\t\t\t\t<th style=\"text-align: left\">vD</th>\n\t\t\t\t\t<th style=\"text-align: left\">vE</th>\n\t\t\t\t\t<th style=\"text-align: left\">vG</th>\n\t\t\t\t\t<th style=\"text-align: left\">vI</th>\n\t\t\t\t\t<th style=\"text-align: left\">vK</th>\n\t\t\t\t\t<th style=\"text-align: left\">vL</th>\n\t\t\t\t\t<th></th>\n\t\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t\t<tr>\n\t\t\t\t\t<td style=\"text-align: left\">F</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">F</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">F</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">F</td>\n\t\t\t\t\t<td style=\"text-align: left\">T</td>\n\t\t\t\t\t<td style=\"text-align: left\">3E</td>\n\t\t\t\t\t<td style=\"text-align: left\">3G</td>\n\t\t\t\t\t<td style=\"text-align: left\">3B</td>\n\t\t\t\t\t<td style=\"text-align: left\">3D</td>\n\t\t\t\t\t<td style=\"text-align: left\">3J</td>\n\t\t\t\t\t<td style=\"text-align: left\">3F</td>\n\t\t\t\t\t<td style=\"text-align: left\">3L</td>\n\t\t\t\t\t<td style=\"text-align: left\">3I</td>\n\t\t\t\t\t<td></td>\n\t\t\t</tr>\n\t</tbody>\n</table>\n<p>Now I have been whittling down the options with the following Python code,\nwhere <code>df</code> is the name of the DataFrame.</p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-python\" data-lang=\"python\"><span class=\"line\"><span class=\"cl\"><span class=\"kn\">from</span> <span class=\"nn\">itertools</span> <span class=\"kn\">import</span> <span class=\"n\">combinations</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"kn\">from</span> <span class=\"nn\">collections</span> <span class=\"kn\">import</span> <span class=\"n\">Counter</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"kn\">import</span> <span class=\"nn\">pandas</span> <span class=\"k\">as</span> <span class=\"nn\">pd</span>\n</span></span><span class=\"line\"><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">IN</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;FBEID&#39;</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">OUT</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;H&#39;</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">ORDER</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;CAG&#39;</span> \n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">ix</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"n\">IN</span><span class=\"p\">:</span>\n</span></span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">ix</span> <span class=\"o\">&amp;=</span> <span class=\"n\">df</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">]</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"n\">OUT</span><span class=\"p\">:</span>\n</span></span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">ix</span> <span class=\"o\">&amp;=</span> <span class=\"o\">~</span><span class=\"n\">df</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">]</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">for</span> <span class=\"n\">x</span><span class=\"p\">,</span> <span class=\"n\">y</span> <span class=\"ow\">in</span> <span class=\"n\">combinations</span><span class=\"p\">(</span><span class=\"n\">ORDER</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">):</span>\n</span></span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">ix</span> <span class=\"o\">&amp;=</span> <span class=\"p\">(</span><span class=\"o\">~</span><span class=\"n\">df</span><span class=\"p\">[</span><span class=\"n\">x</span><span class=\"p\">]</span> <span class=\"o\">|</span> <span class=\"n\">df</span><span class=\"p\">[</span><span class=\"n\">y</span><span class=\"p\">])</span>\n</span></span><span class=\"line\"><span class=\"cl\">\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"sa\">f</span><span class=\"s1\">&#39;Options remaining: </span><span class=\"si\">{</span><span class=\"nb\">sum</span><span class=\"p\">(</span><span class=\"n\">ix</span><span class=\"p\">)</span><span class=\"si\">}</span><span class=\"s1\">&#39;</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">counters</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">index</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;vA&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vB&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vD&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vE&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vG&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vI&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vK&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;vL&#39;</span><span class=\"p\">]</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"k\">for</span> <span class=\"n\">x</span> <span class=\"ow\">in</span> <span class=\"n\">index</span><span class=\"p\">:</span>\n</span></span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">counters</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">Counter</span><span class=\"p\">(</span><span class=\"n\">df</span><span class=\"p\">[</span><span class=\"n\">ix</span><span class=\"p\">][</span><span class=\"n\">x</span><span class=\"p\">]))</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"n\">dff</span> <span class=\"o\">=</span> <span class=\"n\">pd</span><span class=\"o\">.</span><span class=\"n\">DataFrame</span><span class=\"p\">(</span><span class=\"n\">counters</span><span class=\"p\">,</span> <span class=\"n\">index</span><span class=\"o\">=</span><span class=\"n\">index</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">fillna</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">astype</span><span class=\"p\">(</span><span class=\"nb\">int</span><span class=\"p\">)</span>\n</span></span><span class=\"line\"><span class=\"cl\"><span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">dff</span><span class=\"o\">.</span><span class=\"n\">replace</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">,</span> <span class=\"s2\">&#34;&#34;</span><span class=\"p\">))</span>\n</span></span></code></pre></div><p>The <code>ix</code> variable is a Pandas index selector. For each character of <code>IN</code>, the\ncorresponding column must be True. For each character of <code>OUT</code>, the\ncorresponding column must be False. And finally, for each of the undetermined\nteams in <code>ORDER</code>, which are sorted by their current ranking, it cannot be that the\nlower-ranked team gets in while the higher ranked team does not. In Boolean logic\nterms, this is &ldquo;x implies y&rdquo;, which is the same as &ldquo;(not x) or y.&rdquo;</p>\n<p>Then <code>sum(ix)</code> will get you the number of selected columns. Finally, I arranged\neverything into a new table that has as its rows the <code>vX</code> labels, as its\ncolumns, the <code>3X</code> labels, and as its values, the number of scenarios left\nfor which that matchup is possible:</p>\n<pre tabindex=\"0\"><code>Options remaining: 8\n\n   3E 3C 3J 3G 3B 3D 3I 3A 3F 3L 3K\nvA  7  1                           \nvB        1  7                     \nvD              8                  \nvE                 8               \nvG        2           2  4         \nvI                          8      \nvK  1                 3        4   \nvL        1           3           4\n</code></pre><p>You can see from this that one of the most disruptive scenarios left would be\nfor 3C to play against 1A, but there is only one scenario left in which\nScotland makes it through at all, which is that every single match today goes\ntheir way. That would mean Croatia losing by 3 or more, Congo failing to win,\nand some kind of lopsided win between Austria and Algeria.</p>\n",
      "date_published": "2026-06-27T10:26:28-07:00",
      "id": "https://nathangrigg.com/2026/06/world-cup-scenario-planning/",
      "title": "World Cup Scenario Planning",
      "url": "https://nathangrigg.com/2026/06/world-cup-scenario-planning/"
    },
    {
      "content_html": "<p>I rent a post office box. It is an unnecessary expense, but I enjoy a walk\nevery now and then to pick up the mail. My youngest child often joins me. He\nenters, takes a big sniff, and tells me it is his favorite smell. It smells\nlike mildew.</p>\n<figure class=\"center\"><img src=\"/2026/06/post-office-box/post-office.jpg\" class=\"center\"\n    alt=\"Walls of mail boxes inside of a US Postal Service office\">\n</figure>\n\n<p>I also have a return address stamp, typeset in <a href=\"https://en.wikipedia.org/wiki/Gorton_(typeface)\">Gorton</a> <a href=\"https://shifthappens.site/typography/\">Perfected</a>,\npart of Marcin Wichary&rsquo;s <a href=\"https://shifthappens.site\">Shift Happens</a> project.</p>\n<figure class=\"center\"><img src=\"/2026/06/post-office-box/stamp.jpg\" class=\"center\"\n    alt=\"Return address stamp\">\n</figure>\n\n",
      "date_published": "2026-06-17T19:44:03-07:00",
      "id": "https://nathangrigg.com/2026/06/post-office-box/",
      "title": "Post Office Box",
      "url": "https://nathangrigg.com/2026/06/post-office-box/"
    },
    {
      "content_html": "<p>If my 7-year-old ever sees me &ldquo;hacking,&rdquo; that is, typing terminal commands, he asks to help, which means me transcribing commands for him to type.</p>\n<p>I started to explain IP addresses to him after he configured part of the network, but he told me he knows what an IP address is, he saw it on Magic School Bus.</p>\n",
      "date_published": "2026-06-15T13:00:23-07:00",
      "id": "https://nathangrigg.com/2026/06/tbnjgs/",
      "url": "https://nathangrigg.com/2026/06/tbnjgs/"
    },
    {
      "content_html": "<p>With my new <a href=\"https://nathangrigg.com/2026/04/building-a-computer/\">home</a> <a href=\"https://nathangrigg.com/2026/05/home-server-software/\">server</a>, I&rsquo;ve made some changes (improvements,\nhopefully) to my backup system.</p>\n<h2 id=\"previous-backup-systems\">Previous backup systems</h2>\n<p>To back up my Mac, I’ve always started with <a href=\"https://en.wikipedia.org/wiki/Time_Machine_(macOS)\">Time Machine</a>. It has good\noperating system support, and it can do frequent incremental backups, even when\nyou aren’t connected to the backup disk. It isn’t great for long-term backups\nthough, because every year or so, it gets corrupted and you have to start over\nfrom scratch, losing old versions of your files. It seems to be worse when\nbacking up over the network, so I only use Time Machine to a directly\nconnected hard drive.</p>\n<p>I’ve used <a href=\"https://en.wikipedia.org/wiki/Backblaze\">Backblaze</a>, which does internet backups. You can also configure\nit to keep old versions of your files, although beyond a certain point you have\nto pay per gigabyte. Backblaze has been pretty reliable, although if you have\nmultiple devices, the per-month price starts to add up.</p>\n<p>I’ve used <a href=\"https://www.arqbackup.com\">Arq</a>, backing up either to a network drive or to Backblaze B2.\nThis seems to work pretty well. The concept is very similar to Backblaze except\nthat it is more flexible on where you put the data. I don’t use this on my main\nmachine any more, but my kids do on their laptops because it is good about\nsending data over the internet to my home server (using <a href=\"https://rustfs.com\">RustFS</a> to\nrun an S3-compatible server).</p>\n<h2 id=\"zfs-network-backups\">ZFS network backups</h2>\n<p>All of these backup systems do somewhat complex things to allow you to store\nmultiple versions of files, which is a very important feature for a backup\nsystem, in case you accidentally delete or change something and you want to get\nit back.</p>\n<p>A different strategy is to make the backup client dumb but the storage system\nsmart. Since I’m using <a href=\"https://en.wikipedia.org/wiki/ZFS\">ZFS</a> for my home server, I can do snapshotting and\nversioning there. Not only does this simplify things for the client, it gives\nme more flexibility, for example, to keep many snapshots on the large home\nserver but only send one or two versions to the smaller offsite backup drives.</p>\n<h3 id=\"superduper\">SuperDuper</h3>\n<p><a href=\"https://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html\">SuperDuper</a> focuses on exact copies of the entire filesystem. It typically\nuses an APFS-formatted external drive, but it also has support for network\nshares. As of MacOS 26, these network backups use Apple&rsquo;s new sparse image\n(ASIF) format. On the server side, this looks like a giant file big enough to\nstore all of your data.</p>\n<p>After each backup, I have SuperDuper trigger a ZFS snapshot, which allows me to\ntravel back in time to see a day&rsquo;s backup even after future SuperDuper &ldquo;Smart\nUpdates&rdquo; have changed the live version of the sparse image on the server. And\nZFS doesn&rsquo;t have to store an entire copy of each sparse image, just the parts\nthat have changed from one instance to the next.</p>\n<p>You don&rsquo;t get a fancy browser that can see all former versions of a file, the\nway that Time Machine does. From MacOS&rsquo; point of view, you have an entirely\nseparate sparse image per backup, just stored in a way that they don&rsquo;t have to\nduplicate unchanged data. You do get all of the Apple-native file features,\nsince the backup targets are full APFS filesystems.</p>\n<h3 id=\"carbon-copy-cloner\">Carbon Copy Cloner</h3>\n<p><a href=\"https://bombich.com\">Carbon Copy Cloner</a> is more flexible when making copies to an attached\nhard drive, including using APFS snapshots to store multiple versions of a\nfile, the way that Time Machine does. But it is much more limited when using\nnetwork storage: it copies individual files and doesn&rsquo;t support versioning\nor other APFS features.</p>\n<p>I find it useful, especially when combined with ZFS snapshots, because it makes\nit easy to see a file&rsquo;s change history over time. It is more transparent than\nsparse images, even if it is less faithful.</p>\n<h2 id=\"backups-of-a-zfs-system\">Backups of a ZFS system</h2>\n<p>I also want an offsite backup, to make sure that I&rsquo;m safe in case both my Mac\nand home server are taken out at the same time. For this, I use an old hard\ndrive big enough to store just a few of the latest snapshots, and a Perl\nscript called <em>syncoid</em> (part of the snapshot manager <a href=\"https://github.com/jimsalterjrs/sanoid\">sanoid</a>).</p>\n<p>The backup script looks essentially like this:</p>\n<pre tabindex=\"0\"><code>syncoid --identifier=offsite --compress=none \\\n    --recursive --sendoptions=w \\\n    --delete-target-snapshots \\\n    main offsite/main\n</code></pre><p>The first time this is run, it creates a snapshot of the &lsquo;main&rsquo; dataset\nand then copies that snapshot to the offsite dataset, which is stored\non the external drive. The identifier is used as part of the snapshot name,\nin case you want to set up multiple backup targets.</p>\n<p>On subsequent runs, it creates a new snapshot, and then sends everything\nthat has changed since the previous syncoid snapshot (including any snapshots\nthat you make by other means) to the backup target. Then it deletes the\nprevious snapshot.</p>\n<p>Compression is turned off because I am copying to a USB hard drive, not over\nthe network (although syncoid will work over SSH as well).  The &lsquo;w&rsquo; option\nsends raw encrypted datasets, which isn&rsquo;t strictly necessary since you can\nalways configure the target to re-encrypt everything. Deleting the target\nsnapshots means that if you delete a snapshot on the source, it gets\ndeleted from the target.</p>\n<p>I keep two identical backups, one connected that is receiving daily syncs, and\nthe other at my office. Every 2-3 weeks I swap them, so that the office copy\nisn&rsquo;t more than a month out of date.</p>\n",
      "date_published": "2026-06-13T15:47:20-07:00",
      "id": "https://nathangrigg.com/2026/06/zfs-network-backup/",
      "title": "Mac Network Backups with ZFS",
      "url": "https://nathangrigg.com/2026/06/zfs-network-backup/"
    },
    {
      "content_html": "<p>Earlier this year, I built a <a href=\"https://nathangrigg.com/2026/04/building-a-computer/\">new home server</a> and data storage system. From\nthe hardware side of things, this was a whole new experience for me. But the\nsoftware side also gave me a lot of opportunities to experiment.</p>\n<h2 id=\"synology-truenas-docker-etc\">Synology, TrueNAS, Docker, etc.</h2>\n<p>My previous storage system was <a href=\"https://en.wikipedia.org/wiki/Synology\">Synology</a>, which is appliance-style\nsoftware. The operating system is set up to be mostly foolproof, and additional\nsoftware generally requires applications to be packaged specifically for\nSynology.</p>\n<p>It is very convenient to have so many decisions made for you, and my original\nplan was to use <a href=\"https://en.wikipedia.org/wiki/TrueNAS\">TrueNAS</a> as a replacement. Like Synology, TrueNAS has a\nweb-based UI to manage the core services, and an app store to download\nadditional software, all very connect-the-bricks. And if you can’t find an app\nyou want, you can configure anything by using <a href=\"https://en.wikipedia.org/wiki/Docker_(software)\">Docker</a>.</p>\n<p>The more I considered it, though, the more I realized that I didn’t want the\nlimitations of being inside an opinionated system. When everything goes right\nwith appliance-style software, it’s great. But if you veer too far away from\nthe defaults, or if you run into problems, you find yourself fighting against\nthe system instead of working with it.</p>\n<p>Even Docker, which can make handling multiple services and dependencies both\neasier and more reliable, adds a level of complexity that can be a drag.\nBesides, I spend my time professionally running containerized, productionized\nservices, writing config files that are used to generate other config files\nthat eventually run and manage the services.</p>\n<h2 id=\"bare-metal\">Bare metal</h2>\n<p>So instead, I decided to go bare metal, and I installed Debian. I have some\nexperience with this from my <a href=\"https://nathangrigg.com/2023/12/new-computer/\">Mini PC</a> that I was using to complement the\nSynology. It is very common for software to have a Debian installer. And it\nisn’t too hard to write or change a <a href=\"https://en.wikipedia.org/wiki/Systemd\">systemd</a> config file if you want to\ninstall something more obscure or customize things a little. I think you do\nneed a better understanding of how the different parts of the system work\ntogether, but as a result, I feel like there is no magic, which means there is\nno limit to what I can do.</p>\n<h2 id=\"void-linux\">Void Linux</h2>\n<p>And then, mostly by chance, I stumbled into a Linux distribution called <a href=\"https://voidlinux.org/\">Void\nLinux</a>. I was most intrigued by its service management system, which is\ncalled <a href=\"https://docs.voidlinux.org/config/services/index.html\">Runit</a>, because instead of config files it has shell scripts. I don’t\nhave anything in particular against systemd, but if my goal in going bare metal\nwas to get rid of abstractions and config files, then this seemed like an even\nbetter fit for my hobby project.</p>\n<p>One downside is that not as much software is packaged for Void compared to\nDebian. And I probably wouldn’t recommend Void to someone who isn’t comfortable\nwith or willing to learn to write shell scripts. Also, setting up Runit\nservices can involve a little bit of boilerplate, which some people (not me)\nare allergic to.</p>\n<p>But if you clear those hurdles, the simplicity is your reward. The system boot\nscripts are just shell scripts. Service definitions are just shell scripts that\nare auto-restarted every time they terminate or fail. Instead of a complex\ndependency management system, your service can just quit if something is\nmissing, and the next time it starts, maybe things will be in a better state.\nInstead of writing a config file to create a custom <code>/run</code> directory or <code>/tmp</code>\ndirectory, you can just put a <code>mkdir</code> inside the shell script. To enable or\ndisable a service, you put a symlink into the <code>/var/service</code> folder.  To write\nlogs, you just print messages to stdout. And so on.</p>\n<p>Anyway, that is the current state of my home server. It feels light and fun and\nunixy instead of cumbserome and enterprisey.</p>\n",
      "date_published": "2026-05-17T17:28:49-07:00",
      "id": "https://nathangrigg.com/2026/05/home-server-software/",
      "title": "Software For My New Home Server",
      "url": "https://nathangrigg.com/2026/05/home-server-software/"
    },
    {
      "content_html": "<p>I was playing around with IPv6 on the VPS that hosts this blog when I realized\nthat, at least over IPv6, I no longer need virtual hosts.</p>\n<p>In the old, old days, a &ldquo;host&rdquo; was a physical computer name, mapped to an IP\naddress by DNS. As HTTP spread, it made sense to host multiple websites on the\nsame machine, so browsers were required to send the &ldquo;Host&rdquo; header to tell the\nserver what site they were looking for. Now a single server could do something\ndifferent in response to www.example.com vs example.com.</p>\n<p>Today, the vast majority of the web is served through a Content Delivery\nNetwork (CDN) such as Cloudflare, where millions of sites are assigned to the\nsame IP address, and the Host header is used to route the request through the\nCDN to see if there is a cached version, falling back to the &ldquo;origin&rdquo; server if\nnot. At that point, the origin server is likely serving a dozen or more\nsites, and it again looks at the Host header to actually figure out what\ncontent to return.</p>\n<p>In an nginx config on the origin server, this might look like this:</p>\n<pre tabindex=\"0\"><code>server {\n    listen 80;\n    listen [::]:80;\n    server_name example.com;\n    ...\n}\n</code></pre><p>This says &ldquo;use the following settings if you get any request on IPv4 port 80,\nor IPv6 port 80, as long as the host matches example.com.&rdquo;</p>\n<p>The server that hosts this blog hosts a dozen others, many of which are just\nredirects like www.nathangrigg.com -&gt; nathangrigg.com. Until today, these all\nused the same IP address, with an nginx config to route the different virtual\nhosts to different sites on the same server.</p>\n<p>While I wouldn&rsquo;t want to pay for that many IPv4 addresses, which typically cost\na couple dollars each per month, IPv6 addresses are plentiful. My host will\ngive me, at no charge, a &ldquo;/64 block&rdquo;, meaning a 64-bit prefix for which I can\nuse every address contaning that prefix. Since IPv6 address are 128 bits long,\nthat is 2^64 possible addresses to use.</p>\n<p>So I added a startup script on my server that runs</p>\n<pre tabindex=\"0\"><code>ip -6 addr add 2a01:7e03:e001:1ac::1/64 dev eth0\nip -6 addr add 2a01:7e03:e001:1ac::2/64 dev eth0\n...\n</code></pre><p>(That is my assigned 64-bit prefix in four groups of 16, and the double colon\nmeans &ldquo;a bunch of zeroes&rdquo;.)</p>\n<p>Then I updated my DNS entries to map each domain to a different IP address, and\nupdated my server block to say</p>\n<pre tabindex=\"0\"><code>server {\n    listen [2a01:7e03:e001:1ac::1]:80\n    ...\n}\n</code></pre><p>(I had to keep a separate server block with virtual hosts for the IPv4-based routing.)</p>\n<p>Now, over IPv6, nginx uses the incoming address rather than the host name to\ndecide what to serve.</p>\n<p>Is it better? Probably not. But it lets me pretend like I have a different\ncomputer for each little website.</p>\n<p>If you want to see it in action, try <code>curl -vIL6 www.nathangrigg.com</code>, and you\ncan watch the procession from www-port-80 to www-port-443 to bare\nnathangrigg.com. (<code>v</code> for verbose, <code>I</code> for headers only, <code>L</code> to follow\nredirects, and <code>6</code> to force IPv6. If it fails for you, you may have to remove\nthe 6 and watch the boring IPv4 version, where the IP address is the same for\nevery request.)</p>\n",
      "date_published": "2026-04-25T16:22:26-07:00",
      "id": "https://nathangrigg.com/2026/04/artisanal-web-server/",
      "title": "Artisanal Web Server",
      "url": "https://nathangrigg.com/2026/04/artisanal-web-server/"
    },
    {
      "content_html": "<h2 id=\"catalyst\">Catalyst</h2>\n<p>I like having network-based storage, so I can have a place to store backups,\nlarge files that I’m not using, copies of media that I’ve purchased,\naudiobooks, etc.</p>\n<p>For the last 10 years, I’ve accomplished this with a four-bay Synology, which I\neventually replaced with a second four-bay Synology, keeping the old one as a\nbackup.</p>\n<p>You can run various programs on the Synology because it is basically a\nlow-powered server. The UI was helpful for me as a beginner.</p>\n<p>In the long run, however, I wanted more customization than I could get from\nSynology, which eventually led me to <a href=\"https://nathangrigg.com/2023/12/new-computer/\">buy a mini\nPC</a> to run everything except the\nbasic file server and backup functions.</p>\n<p>Finally, I decided that I wanted even more customizability, I wanted a way to\nput all of my drives in one machine, and I was itching for a fun side project. I\nbriefly looked into other network storage options and decided that, since I had\nnever built a computer from scratch before, it would be fun to try a custom\nbuild.</p>\n<h2 id=\"parts\">Parts</h2>\n<p>I don’t remember exactly how it all came together. There are a lot of options,\na lot of decision to be made, and I didn’t really know what I was doing.</p>\n<p>I wanted room for a lot of disks and the ability to hot-swap, which led me\nto the <a href=\"https://www.jonsbo.com/en/products/N5Black.html\">Jonsbo N5 case</a>,\nwhich holds 12 disks. It was great for a first build because it is quite\nspacious.</p>\n<p>I wanted a way to access it without a keyboard or monitor, so my main\nrequirement for the motherboard was something server-grade with\n<a href=\"https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface\">IPMI</a>.\nThe motherboard I bought has a separate ethernet port that presents a web\ninterface to configure the firmware settings as well as to connect remotely to\na virtual monitor.</p>\n<p>I wanted a CPU with integrated graphics, and I went with a mid-line Intel chip\n(“Core Ultra 5”).</p>\n<p>I also needed a <a href=\"https://en.wikipedia.org/wiki/Host_adapter\">host bus adapter</a>\nto be able to connect so many hard drives to the motherboard. This goes in a\nPCIe slot.</p>\n<p>Finally, I wanted ECC RAM (very expensive thanks to AI), and some SSDs to run\nthe operating system. Plus a power supply, a bunch of cables, and some fans.</p>\n<h2 id=\"build\">Build</h2>\n<p>The build was like an expensive Lego project except I might have bought the\nwrong pieces. It really was fun to see all of the different pieces come\ntogether.</p>\n<p>I had a hard time getting the CPU cooler attached and I was worried I had done\nit wrong.</p>\n<p>I had some annoying fan issues because I had some giant 14-inch fans for the\nfront of the case that max out at 800 RPM. If they went below 300 RPM, the\nmotherboard would think they had failed and start pulsing all of the fans, or\nelse blowing them all full blast. I eventually solved this by connecting them\nto a fan hub so that the motherboard wouldn’t know how fast they were going.\nI’m sure there are better ways.</p>\n<p>Those issues notwithstanding, I did manage to boot it up on the first try.\nUnfortunately, I had a couple of suspicious crashes in the first few days,\nmostly when I was transferring large files to the new computer. I realized that\nbefore I started trying to install anything, I should have done some diagnostic\nchecks.</p>\n<p>When I ran <a href=\"https://www.memtest86.com/\">MemTest86</a> to check whether there were\nRAM issues, it froze four seconds into the first test. It failed so hard that I\nfigured I must have done something wrong with seating the CPU, or that the\nmotherboard was faulty.</p>\n<p>I tried reseating the CPU to see if I’d screwed it up, but eventually resigned\nmyself to buying more RAM. This was a painful choice because RAM was 1/3 the\ncost of the full build. But it was the right choice; the new RAM passed\nMemTest86, and I got a refund for the first batch of RAM.</p>\n<p>So with that, I had a working computer. It was a really fun way to spend some\nof my free time. I wouldn&rsquo;t say it was easy or frustration-free, but I learned\na lot. It was also a good complement to my day job, where I wrangle computers\nlike they&rsquo;re herds of cattle without ever seeing or touching a single one.</p>\n<figure class=\"center\"><img src=\"/2026/04/building-a-computer/computer.jpeg\" class=\"center\"\n    alt=\"The computer sits on a shelf in the garage, with a cable around it for earthquake safety.\" width=\"500\"><figcaption>\n      <p>The computer sits on a shelf in the garage, with a cable around it for earthquake safety.</p>\n    </figcaption>\n</figure>\n\n",
      "date_published": "2026-04-13T20:07:39-07:00",
      "id": "https://nathangrigg.com/2026/04/building-a-computer/",
      "title": "Building a Computer",
      "url": "https://nathangrigg.com/2026/04/building-a-computer/"
    },
    {
      "content_html": "<p>Writing go code is a thousand paper cuts but then you get that nice beautiful binary and you put it wherever you want and I&rsquo;m still not sure it&rsquo;s worth it.</p>\n",
      "date_published": "2026-03-02T11:37:41-08:00",
      "id": "https://nathangrigg.com/2026/03/ygvghg/",
      "url": "https://nathangrigg.com/2026/03/ygvghg/"
    },
    {
      "content_html": "<p>Well done <a href=\"https://brucespringsteen.net/news/2026/streets-of-minneapolis/\">Bruce Springsteen</a>. I&rsquo;m touched by the designation &ldquo;Winter of &lsquo;26.&rdquo; Some events are too momentous for a descriptive label. Here&rsquo;s hoping we remember it as a turning point, a wake-up call to the complacent.</p>\n",
      "date_published": "2026-01-28T15:40:46-08:00",
      "id": "https://nathangrigg.com/2026/01/rrjynz/",
      "url": "https://nathangrigg.com/2026/01/rrjynz/"
    },
    {
      "content_html": "<p>US politics are more about identity and power than principles, even though we\nlike to pretend otherwise. In my high school in conservative, rural Idaho, we\nwould debate the virtues of small, limited government, second amendment\nfreedoms, family values candidates, and I was duped into thinking the choice\nwas between Platform A or Platform B, when it was really a choice between\ngiving power to a “friend” or an “enemy.”</p>\n<p>It took me an embarrassingly long time to realize that my principles were more\naligned with the Democrats, even though I felt “more at home” among the\nRepublicans. But I have also changed, trading Idaho for Seattle, then Los\nAngeles, to the point where today I feel more at home in a city coffee shop\nthan a county fair or a church service.</p>\n<p>While I have always voted against Trump, I have supported some candiates that I\nnow strongly regret. And I try my best to see the humanity in those who did\nvote for him, because everyone has their own journey.</p>\n<p>But today, everyone must oppose the Trump administration, with its calculated,\nprovocative, performative violence, including but not limited to the killing of\nRenee Good and Alex Pretti. We cannot accept the lies, obstruction, and\ncover-ups that have followed. Anybody involved in or responsible for these\nviolent acts or their cover-ups should be impeached, removed from office,\nand/or put in jail for their crimes. Every person in power who refuses to hold\nthese offenders to account should be voted out of office and remembered as the\ncowards that they are.</p>\n<p>We cannot wait until the next election to take power away from these monsters.\nSpeak up today, set the record straight if you&rsquo;ve had a change of heart. Call\nyour representatives and tell them to defend us and enforce our laws.</p>\n<p>ICE is not our friend; Trump and his enablers are our enemy.</p>\n",
      "date_published": "2026-01-25T17:04:30-08:00",
      "id": "https://nathangrigg.com/2026/01/renee-and-alex/",
      "title": "Taking a Stand",
      "url": "https://nathangrigg.com/2026/01/renee-and-alex/"
    },
    {
      "content_html": "<p>I got a new watch.</p>\n<p>I’ve almost exclusively worn an Apple Watch for the past several years. I still\nwear one when exercising and sleeping, and I plan to still wear it on some\nother occasions, but I wanted to see what it was like to go back, shall we say,\nto a simpler time.</p>\n<p>My initial feelings are a happy dose of nostalgia. Back before all of our\nphones and watches and cars were synchronized to NIST time, I would carefully\nsynchronize my Timex digital watch to the school bell time. It was satisfying\nto know exactly how much time was left in class (or passing period) while most\nof my classmates just had to wait and wonder when freedom would come (or end).</p>\n<p>With a &ldquo;dumb&rdquo; watch, there is this same sense of satisfaction, that I know the\nprecise time not through the wonders of the internet, but because I made the\neffort to accurately set my watch.</p>\n<h1 id=\"a-gmt-complication\">A GMT Complication</h1>\n<p>My new watch is a GMT watch, which is a popular watch style over the last\ncentury or so, because it makes it easy to know the time in a second or even\nthird location, and can make it easier to change the time as well.</p>\n<p>There are many different styles of GMT watch, but they are usually\ndistinguished by a separate “GMT hand” that makes one revolution per 24 hours,\ncompared to a traditional hour hand that revolves once per 12 hours. A GMT\nwatch typically has the traditional hour hand as well, which most people call\nthe “local hour hand,” because it tracks the time of your current location.\nBoth of these hands are typically aligned to the same minute hand.</p>\n<p>Being non-smart watches, they are relatively simple to configure. A <em>true GMT</em>\nor <em>flyer GMT</em> lets you adjust the time (minutes and hours) on all three\nhands simultaneously, and then jump the local hour hand forward or backwards an\nhour at a time. On a <em>caller GMT</em> or <em>office GMT</em>, the jump function moves the\nGMT hand forward or backwards an hour at a time. Either way, you can track both\nthe local time and a separate reference time, but the caller GMT is more\ncumbersome to travel with, because if you change time zones, you have to reset\nthe watch the same way you would any watch, and then also fix the GMT hand to\npoint back to whatever reference time you want to track. A flyer GMT lets\nyou quickly adjust the local time without messing up the GMT hand at all.</p>\n<p>Many GMT watches also feature a rotating bezel labeled on a 24-hour scale. This\ngives you a way to quickly change the meaning of the GMT hand by shifting the\nlabels instead of the hand. Hence you have the ability to track a potentially\nthird time zone. I say potentially because on most GMT watches with a bezel,\nthe bezel is the only set of 24-hour labels, so if you rotate it, you might not\nknow exactly where the GMT hand is pointing on the “natural” set of labels.</p>\n<p>Here are some examples of tracking two or three time zones on a GMT watch:</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock1.svg\" class=\"center\"\n    alt=\"It is 10:11 a.m. in Central European Summer Time, and the GMT hand is showing 08:11 UTC.\" width=\"300\"><figcaption>\n      <p>It is 10:11 a.m. in Central European Summer Time, and the GMT hand is showing 08:11 UTC.</p>\n    </figcaption>\n</figure>\n\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock2.svg\" class=\"center\"\n    alt=\"By rotating the dial four 15-degree clicks, we can read the New York Daylight Saving Time (UTC−4) as 04:11.\" width=\"300\"><figcaption>\n      <p>By rotating the dial four 15-degree clicks, we can read the New York Daylight Saving Time (UTC−4) as 04:11.</p>\n    </figcaption>\n</figure>\n\n<p>In these examples, note that the twelve o&rsquo;clock position represents midnight\nUTC, and in the second example, the 20 (which is −4 modulo 24) lines up with\nthis slot so that we can read UTC−4. And even with the bezel rotated, you get\na sense of the UTC time because you will at least remember where 0, 6, 12, and\n18 would be on the unrotated bezel.</p>\n<h1 id=\"open-to-interpretation\">Open to interpretation</h1>\n<p>Although a GMT watch only has a few configurable parts (minutes, local hour,\nGMT hour, and bezel rotation),  you get to choose what the configuration should\nbe. If you really wanted to, you could have the “local time” always be your\nhome time and the “GMT hand” be your current local time.</p>\n<p>I knew I wanted to use the local hour hand the normal way, with the local time\nof wherever I happen to be (usually in Los Angeles). At first, I thought that I\nwould use the GMT hand for UTC, and then rotate the bezel to whatever second\ntime zone I was actually interested in. But I was quickly annoyed that the\ndirection of the GMT hand didn’t really have any meaning to me.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock3.svg\" class=\"center\"\n    alt=\"At 9:29 p.m. Los Angeles winter time, it is 05:29 UTC\" width=\"300\"><figcaption>\n      <p>At 9:29 p.m. Los Angeles winter time, it is 05:29 UTC</p>\n    </figcaption>\n</figure>\n\n<p>Next, I decided to use my home time (or at least UTC−8, more on that in a bit)\nfor the GMT hand. This way, no matter where I am in the world, the GMT hand in\nthe upper half means it is night in Los Angeles, and in the lower half means it\nis daytime.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock4.svg\" class=\"center\"\n    alt=\"Still 9:29 p.m. in Los Angeles, with the local 24-hour time of 21:29 shown on the GMT hand\" width=\"300\"><figcaption>\n      <p>Still 9:29 p.m. in Los Angeles, with the local 24-hour time of 21:29 shown on the GMT hand</p>\n    </figcaption>\n</figure>\n\n<p>Then I realized that, because my watch doesn’t have a fixed set of labels, I\ncould orient the “natural” 24-hour scale with midnight at the bottom and noon\nat the top, imitating the path of the sun. I decided to keep the bezel oriented\nwith the zero marker at 6:00, so that I can read the Los Angeles 24-hour time\noff the bezel, if I want.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock5.svg\" class=\"center\"\n    alt=\"Again 9:29 p.m. in Los Angeles, with the local 24-hour time of 21:29 shown and the bezel rotated so that noon is at the top and midnight at the bottom.\" width=\"300\"><figcaption>\n      <p>Again 9:29 p.m. in Los Angeles, with the local 24-hour time of 21:29 shown and the bezel rotated so that noon is at the top and midnight at the bottom.</p>\n    </figcaption>\n</figure>\n\n<p>Then when traveling, I can intuitively read my home time off the GMT hand.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock6.svg\" class=\"center\"\n    alt=\"Jumping the local time to 2:29 p.m. (Tokyo time), the GMT hand and bezel still pointing to Los Angeles time of 21:29.\" width=\"300\"><figcaption>\n      <p>Jumping the local time to 2:29 p.m. (Tokyo time), the GMT hand and bezel still pointing to Los Angeles time of 21:29.</p>\n    </figcaption>\n</figure>\n\n<p>And in this configuration, midnight UTC happens when the GMT is at the two\no&rsquo;clock position, which means I can easily spin the bezel to read a third time\nzone, for example, putting the 1 at two o&rsquo;clock to read UTC+1.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock7.svg\" class=\"center\"\n    alt=\"Still 2:29 p.m. in Tokyo, and 06:29 in UTC&#43;1. Evening in Los Angeles.\" width=\"300\"><figcaption>\n      <p>Still 2:29 p.m. in Tokyo, and 06:29 in UTC+1. Evening in Los Angeles.</p>\n    </figcaption>\n</figure>\n\n<h1 id=\"los-angeles-time-zone-vs-utc8\">Los Angeles time zone vs UTC−8</h1>\n<p>Here is where things get a little speculative because I’ve only had the watch\nfor a month, and haven’t had to transition to summer time. So I have plans but\nmaybe I will change my mind after some experience.</p>\n<p>The Los Angeles time zone is only UTC−8 on winter time. For the rest of the\nyear, we observe Daylight Saving Time, which puts us at UTC−7.</p>\n<p>There are a lot of reasons to leave the GMT hand at (noon-on-top) UTC−8. First\nof all, it makes adjusting for Daylight Saving Time a simple jump of the local\nhour hand. It also preserves the two o&rsquo;clock UTC reference point year round,\nmaking a third time zone a bit easier. It is also somewhat convenient because I\ncan still track (approximate) astronomical noon and midnight.</p>\n<p>But it also means that during the summer, if I want the 24-hour bezel to track\nLos Angeles 24-hour time by default, then it has to be one 15-degree rotation\naskew.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock8.svg\" class=\"center\"\n    alt=\"Local Los Angeles summer time of 6:48 p.m., the bezel rotated to show UTC−7 time of almost 19:00, but the GMT hand also shows the natural solar time of almost 18:00.\" width=\"300\"><figcaption>\n      <p>Local Los Angeles summer time of 6:48 p.m., the bezel rotated to show UTC−7 time of almost 19:00, but the GMT hand also shows the natural solar time of almost 18:00.</p>\n    </figcaption>\n</figure>\n\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/clock9.svg\" class=\"center\"\n    alt=\"Quick spin of the bezel, aligning the 9 with the two o&rsquo;clock marker, to check UTC&#43;9 Tokyo time, where it is nearly 11 a.m.\" width=\"300\"><figcaption>\n      <p>Quick spin of the bezel, aligning the 9 with the two o&rsquo;clock marker, to check UTC+9 Tokyo time, where it is nearly 11 a.m.</p>\n    </figcaption>\n</figure>\n\n<h1 id=\"the-apple-watch-gmt-face\">The Apple Watch GMT Face</h1>\n<p>Many years ago, I tried to use the Apple Watch GMT Face and didn’t last long. I\nlooked at it again to remind myself why I don’t like it.</p>\n<p>First of all, you have no choice about any orientations. The local hand has to\nmatch your local time (but at least it automatically adjusts when you travel).\nAnd of course, up has to be midnight because the programmers might die if they\nhad to add that level of complexity.</p>\n<p>The GMT hand also has to match your local time as well. As I mentioned, I don&rsquo;t\nlike how this messes with my intuition in the admittedly rare case when I&rsquo;m\nin a different time zone.</p>\n<p>You track a second time zone with a software spin of the bezel. Making use of\nthe flexibility of a digital screen, the bezel is two-toned with the colors\nrepresenting night and day, based on the current sunrise and sunset in the\nsecond time zone. Analog GMT watches often have two-toned bezels, with\ntransitions fixed at 6 and 18. (You could argue that 6 a.m. and 6 p.m. are more\nuseful markers than sunrise and sunset in a time zone where you aren&rsquo;t\ncurrently located.)</p>\n<p>Unfortunately, the Apple Watch bezel isn’t actually labeled\nexcept for the index closest to the hand, because otherwise the digital face\ngets too cluttered. Even worse, if you have your watch set to show 12-hour\ntime, the index gets labeled with the 12-hour time, with no indication of a.m.\nvs p.m. except for the color of the bezel.</p>\n<figure class=\"center\"><img src=\"/2026/01/gmt-watch/apple-watch.png\" class=\"center\"\n    alt=\"Apple Watch showing 2:44 p.m. in Los Angeles, 10:44 p.m. in London. You infer that pink is night because it is so long, or from the triangle that still marks midnight. Note that the GMT hand tracks Los Angeles time (currently UTC−8), but with midnight on top, so UTC midnight is at the eight o&rsquo;clock marker.\" width=\"300\"><figcaption>\n      <p>Apple Watch showing 2:44 p.m. in Los Angeles, 10:44 p.m. in London. You infer that pink is night because it is so long, or from the triangle that still marks midnight. Note that the GMT hand tracks Los Angeles time (currently UTC−8), but with midnight on top, so UTC midnight is at the eight o&rsquo;clock marker.</p>\n    </figcaption>\n</figure>\n\n<p>Finally, and this is an ongoing gripe I have against Apple, by default the time\nzone label in the middle of the face says CUP for Cupertino (just like in\niPhone Settings). If that annoys you, you can change it to SF for San\nFrancisco. Neither of those is the correct name of the time zone. Twenty years\nago it was cute to label the Pacific time zone as Cupertino in honor of your\nheadquarters. It’s not cute anymore.</p>\n",
      "date_published": "2026-01-16T15:06:14-08:00",
      "id": "https://nathangrigg.com/2026/01/gmt-watch/",
      "title": "A GMT Watch",
      "url": "https://nathangrigg.com/2026/01/gmt-watch/"
    },
    {
      "content_html": "<p>Many years after starting The Wheel of Time series (I took a few years&rsquo; hiatus between the first 7 and final 7 books), I finished it. Great world, great characters, overall lots of fun.</p>\n<p>Hard to do the series justice, but I guess I would say the first few books are the most exciting, the middle books make for some interesting world building, and Robert Jordan started to pick up steam again before his life was cut short. I don&rsquo;t believe he ever would have ended the series, too many ideas and too many stories.</p>\n",
      "date_published": "2026-01-08T17:40:17-08:00",
      "id": "https://nathangrigg.com/2026/01/fmvfqp/",
      "url": "https://nathangrigg.com/2026/01/fmvfqp/"
    }
  ],
  "language": "en-us",
  "title": "Nathan Grigg",
  "version": "https://jsonfeed.org/version/1.1"
}
