<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: mkt</title>
    <description>The latest articles on DEV Community by mkt (@mkt).</description>
    <link>https://dev.to/mkt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3533376%2F53a2bbf3-6313-480b-bd79-92c15c8c0546.jpg</url>
      <title>DEV Community: mkt</title>
      <link>https://dev.to/mkt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mkt"/>
    <language>en</language>
    <item>
      <title>Visualizing Year/Month/Day Progress in Grafana</title>
      <dc:creator>mkt</dc:creator>
      <pubDate>Sun, 30 Nov 2025 09:21:51 +0000</pubDate>
      <link>https://dev.to/mkt/visualizing-yearmonthday-progress-in-grafana-1mf4</link>
      <guid>https://dev.to/mkt/visualizing-yearmonthday-progress-in-grafana-1mf4</guid>
      <description>&lt;p&gt;As of writing this post (2025/11/30), apparently around 90% of this year has already passed.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1993184119292149949-95" src="https://platform.twitter.com/embed/Tweet.html?id=1993184119292149949"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1993184119292149949-95');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1993184119292149949&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;I use Grafana and Prometheus for system monitoring, and I thought it would be cool to see "How much of this year has passed?" directly on my Grafana dashboard.&lt;/p&gt;

&lt;p&gt;So I built it!&lt;/p&gt;

&lt;p&gt;While I was at it, I decided to show not only the progress of this year but also the progress of this month and today.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Here's what the panel looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfarvz0hff5d6qx4c31b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfarvz0hff5d6qx4c31b.png" alt="Time Progress Panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some trial and error, I managed to create this using only Grafana and Prometheus (PromQL), which I already use every day.&lt;/p&gt;

&lt;p&gt;The PromQL queries to calculate each value (for UTC) are as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This Year (UTC)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(
  ((day_of_year() - 1) * (3600 * 24)) + (time() % (3600 * 24))
)
/
(
  (365 + (day_of_year() != bool day_of_year(vector(time() + 3600 * 24 * 365)))) * 3600 * 24
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;This Month (UTC)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(
  ((day_of_month() - 1) * (3600 * 24)) + (time() % (3600 * 24))
)
/
(
  days_in_month() * (3600 * 24)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Today (UTC)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(time() % (3600 * 24)) / (3600 * 24)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to display progress in a timezone other than UTC, simply add the appropriate offset (in seconds) to your queries.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UTC+9 (Japan Standard Time; JST): add &lt;code&gt;3600 * 9&lt;/code&gt; (= 32400) seconds&lt;/li&gt;
&lt;li&gt;UTC+2: add &lt;code&gt;3600 * 2&lt;/code&gt; (= 7200) seconds&lt;/li&gt;
&lt;li&gt;UTC-5: add &lt;code&gt;3600 * -5&lt;/code&gt; (= -18000) seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Replace the offsets in the queries to match your local timezone.&lt;/p&gt;

&lt;p&gt;Below are JST examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This Year (JST)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
(
  (day_of_year(vector(time() + 3600 * 9) - 1) * 3600 * 24) + ((time() + 3600 * 9) % (3600 * 24) )
)
/
(
  (365 + (day_of_year(vector(time() + 3600 * 9)) != bool day_of_year(vector(time() + 3600 * 9 + 3600 * 24 * 365)))) * 3600 * 24
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;This Month (JST)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
(
  ((day_of_month(vector(time() + 3600 * 9)) - 1) * (3600 * 24)) + ((time() + 3600 * 9) % (3600 * 24))
)
/
(
  days_in_month(vector(time() + 3600 * 9)) * (3600 * 24)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Today (JST)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
((time() + 3600 * 9) % (3600 * 24)) / (3600 * 24)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you know a better way to do this, let me know 🙇‍♂️&lt;/p&gt;
&lt;h2&gt;
  
  
  Test Environment
&lt;/h2&gt;

&lt;p&gt;Here's the environment I used for testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu Server 24.04

&lt;ul&gt;
&lt;li&gt;Grafana: 12.3.0&lt;/li&gt;
&lt;li&gt;Prometheus: 2.45.3 (the version available via apt on Ubuntu 24.04)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: I used Prometheus 2.x for testing. Things might be simpler with 3.x, but I haven't tried yet.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Calculation Formulas
&lt;/h2&gt;

&lt;p&gt;To visualize how much of today, this month, and this year has passed (which I'll call the "progress"), you need to calculate these values.&lt;/p&gt;

&lt;p&gt;The formulas themselves are pretty straightforward: subtract the unixtime at the start of day/month/year from the current unixtime, then divide by the total seconds in day/month/year.&lt;/p&gt;

&lt;p&gt;So, if you can express PromQL queries that match the following formulas, you're good to go:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Today’s Progress (%)=Current Unixtime−Unixtime at Today’s 00:003600×24×100
\text{Today's Progress (\%)} 
= \frac{\text{Current Unixtime} - \text{Unixtime at Today's 00:00}}{3600 \times 24} \times 100
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Today’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at Today’s 00:00&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;




&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;This Month’s Progress (%)=Current Unixtime−Unixtime at 00:00 of the 1st Day of Month3600×24×Days in Month×100
\text{This Month's Progress (\%)} 
= \frac{\text{Current Unixtime} - \text{Unixtime at 00:00 of the 1st Day of Month}}{3600 \times 24 \times \text{Days in Month}} \times 100 &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;This Month’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Days in Month&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at 00:00 of the 1st Day of Month&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;This Year’s Progress (%)=Current Unixtime−Unixtime at 00:00 of Jan 1st3600×24×Days in Year×100 
\text{This Year's Progress (\%)} 
= \frac{\text{Current Unixtime} - \text{Unixtime at 00:00 of Jan 1st}}{3600 \times 24 \times \text{Days in Year}} \times 100 \
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;This Year’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Days in Year&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at 00:00 of Jan 1st&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;span class="mspace"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: I didn't account for daylight saving time (DST) here.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PromQL Queries
&lt;/h2&gt;

&lt;p&gt;Let's implement the formulas above using Prometheus Query Language (PromQL), which provides a number of helpful built-in functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus docs: &lt;a href="https://prometheus.io/docs/prometheus/latest/querying/functions/" rel="noopener noreferrer"&gt;https://prometheus.io/docs/prometheus/latest/querying/functions/&lt;/a&gt;
(&lt;em&gt;Note: Prometheus 2.x and 3.x differ in some literals and syntax. Be careful!&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing to keep in mind: PromQL's time functions operate in UTC. If you want values in your local timezone, you must add an offset manually.&lt;/p&gt;

&lt;p&gt;The following explanations are a bit log, so if you just want the final queries, feel free to scroll back to the TL;DR section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Today's Progress
&lt;/h3&gt;

&lt;p&gt;First, let's calculate today's progress.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;Today’s Progress (%)=Current Unixtime−Unixtime at Today’s 00:003600×24×100
\text{Today's Progress (\%)} = \frac{\text{Current Unixtime} - \text{Unixtime at Today's 00:00}}{3600 \times 24} \times 100
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Today’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at Today’s 00:00&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;In PromQL, you can get the current unixtime by the &lt;code&gt;time()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;You can also calculate today's 00:00 unixtime using the &lt;code&gt;day_of_year()&lt;/code&gt; function, but you don't need to. The number of seconds since 00:00 can be calculated by taking the remainder of the unixtime divided by 86400 (&lt;code&gt;= 3600 * 24&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So we can use modulo directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# UTC
(time() % (3600 * 24)) / (3600 * 24)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-1_today-progress-utc-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-1_today-progress-utc-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to display the value in your local timezone, add the appropriate offset in seconds. For example, for JST (UTC+9), add &lt;code&gt;3600 * 9&lt;/code&gt; (= 32400) seconds.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
((time() + 3600 * 9) % (3600 * 24)) / (3600 * 24)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-2_today-progress-jst-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-2_today-progress-jst-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grafana can multiply by 100 for percentage formatting, so you can leave the raw ratio as-is.&lt;/p&gt;
&lt;h3&gt;
  
  
  This Month's Progress
&lt;/h3&gt;

&lt;p&gt;Next, this month's progress.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;This Month’s Progress (%)=Current Unixtime−Unixtime at 00:00 of the 1st Day of Month3600×24×Days in Month×100
\text{This Month's Progress (\%)} = \frac{\text{Current Unixtime} - \text{Unixtime at 00:00 of the 1st Day of Month}}{3600 \times 24 \times \text{Days in Month}} \times 100
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;This Month’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Days in Month&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at 00:00 of the 1st Day of Month&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;Getting the current unixtime is the same as before, but the tricky part is "Unixtime at 00:00 of the 1st Day of Month" and "Days in Month".&lt;/p&gt;

&lt;p&gt;Obviously, the number of days in a month varies, so you can't use modulo like I did for today's progress.&lt;/p&gt;

&lt;p&gt;Fortunately, PromQL provides the &lt;code&gt;days_in_month()&lt;/code&gt; function for the latter.&lt;/p&gt;

&lt;p&gt;Then, how do you get the unixtime for the 1st day of the month?&lt;/p&gt;

&lt;p&gt;You don't need to calculate it directly. PromQL has a &lt;code&gt;day_of_month()&lt;/code&gt; function that returns the current day of the month, so you can write the numerator as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(day_of_month() - 1) * (3600 * 24)  # Seconds for previous days
+ (time() % (3600 * 24))            # Seconds for today
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, the query for this month's progress looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# UTC
(
  ((day_of_month() - 1) * (3600 * 24)) + (time() % (3600 * 24))
)
/
(
  days_in_month() * (3600 * 24)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-3_this-month-progress-utc-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-3_this-month-progress-utc-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For other timezones, you need to make sure &lt;code&gt;day_of_month()&lt;/code&gt; and &lt;code&gt;days_in_month()&lt;/code&gt; are calculated in your local timezone, not UTC. These functions accept a unixtime (as a vector) as an argument, so you can use your offset-adjusted time.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
(
  ((day_of_month(vector(time() + 3600 * 9)) - 1) * (3600 * 24)) + ((time() + 3600 * 9) % (3600 * 24))
)
/
(
  days_in_month(vector(time() + 3600 * 9)) * (3600 * 24)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-4_this-month-progress-jst-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-4_this-month-progress-jst-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a bit tricky, but it works!&lt;/p&gt;
&lt;h3&gt;
  
  
  This Year's Progress
&lt;/h3&gt;

&lt;p&gt;Finally, this year's progress.&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;This Year’s Progress (%)=Current Unixtime−Unixtime at 00:00 of Jan 1st3600×24×Days in Year×100
\text{This Year's Progress (\%)} = \frac{\text{Current Unixtime} - \text{Unixtime at 00:00 of Jan 1st}}{3600 \times 24 \times \text{Days in Year}} \times 100
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;This Year’s Progress (%)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Days in Year&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Current Unixtime&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Unixtime at 00:00 of Jan 1st&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;Just like with the month, you can use the &lt;code&gt;day_of_year()&lt;/code&gt; function to get the number of seconds since the start of the year:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(day_of_year() - 1) * (3600 * 24) # Seconds for previous days
+ (time() % (3600 * 24))          # Seconds for today
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only missing piece is "Days in Year".&lt;/p&gt;

&lt;p&gt;Years normally have 365 days, but leap years have 366. If you've ever taken a programming class, you've probably written an if-else statement to check for leap years. But PromQL doesn't have if-else clause, and there's no handy &lt;code&gt;days_in_year()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;So, I asked ChatGPT for help, and it suggested the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PromQL to calculate the number of days in the year
365
+ clamp_max(
  (
    (
      ((floor(vector(time()) / 31557600) + 1970) % 400) == bool 0
    )
    +
    (
      (((floor(vector(time()) / 31557600) + 1970) % 4) == bool 0)
      *
      (((floor(vector(time()) / 31557600) + 1970) % 100) != bool 0)
    )
  ),
  1
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;31557600 represents 365.25 days * 86400 seconds, an approximation for a year. By dividing the unixtime by this value, you can get the year difference since 1970.&lt;/p&gt;

&lt;p&gt;Also, you can use the &lt;code&gt;bool&lt;/code&gt; modifier to simulate conditional logic. Comparisons return true/false as 1/0, so you can mimic simple if-else behavior.&lt;/p&gt;

&lt;p&gt;Interesting... but since it's an approximation, there might be some error (I haven't checked how much it is).&lt;/p&gt;

&lt;p&gt;After thinking a bit, I realized we can use PromQL's &lt;code&gt;day_of_year()&lt;/code&gt; function to check for leap years. Specifically, if it is a leap year, the length of the year is 366 days, so if you calculate &lt;code&gt;day_of_year()&lt;/code&gt; at the same time 365 days (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;=3600×24×365= 3600 \times 24 \times 365&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;3600&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;365&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 seconds) later, the value must be different from the current value.&lt;/p&gt;

&lt;p&gt;So, you can calculate the number of days in the year like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PromQL to calculate if this year has 365 or 366 days
365
+
(
  day_of_year() != bool day_of_year(vector(time() + (3600 * 24 * 365)))   # Returns 1 or 0
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final query for this year's progress is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# UTC
(
  ((day_of_year() - 1) * (3600 * 24)) + (time() % (3600 * 24))
)
/
(
  (365 + (day_of_year() != bool day_of_year(vector(time() + 3600 * 24 * 365)))) * 3600 * 24
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-5_this-year-progress-utc-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-5_this-year-progress-utc-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a bit hard to read, but the same logic applies for any timezone. Just adjust the offset in the query to match your local timezone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# JST
(
  (day_of_year(vector(time() + 3600 * 9) - 1) * 3600 * 24) + ((time() + 3600 * 9) % (3600 * 24) )
)
/
(
  (365 + (day_of_year(vector(time() + 3600 * 9)) != bool day_of_year(vector(time() + 3600 * 9 + 3600 * 24 * 365)))) * 3600 * 24
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;GitHub Gist: &lt;a href="https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-6_this-year-progress-jst-promql" rel="noopener noreferrer"&gt;https://gist.github.com/md-irohas/e8289be61c554d0b59fdd36fa085f5fe#file-6_this-year-progress-jst-promql&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, you have all the PromQL queries you need for visualization.&lt;/p&gt;

&lt;p&gt;I haven't thoroughly tested all edge cases, so if you spot a bug, please let me know!&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizing in Grafana
&lt;/h2&gt;

&lt;p&gt;Once the queries are ready, all that's left is to create your favorite panel in Grafana.&lt;/p&gt;

&lt;p&gt;To make a panel like the screenshot above, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a new panel to your dashboard.&lt;/li&gt;
&lt;li&gt;Select "Bar gauge" as the visualization type.&lt;/li&gt;
&lt;li&gt;Choose Prometheus as the data source (assuming you've already added it).&lt;/li&gt;
&lt;li&gt;Paste the queries for year, month, and day progress. Set the legend to "This Year", "This Month", and "Today" respectively.&lt;/li&gt;
&lt;li&gt;In the right sidebar, configure:

&lt;ul&gt;
&lt;li&gt;Bar gauge:

&lt;ul&gt;
&lt;li&gt;Orientation: Horizontal&lt;/li&gt;
&lt;li&gt;Display mode: Retro LCD&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Standard options:

&lt;ul&gt;
&lt;li&gt;Unit: Misc / Percent (0.0-1.0)&lt;/li&gt;
&lt;li&gt;Min: 0&lt;/li&gt;
&lt;li&gt;Max: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This should give you a panel that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfarvz0hff5d6qx4c31b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfarvz0hff5d6qx4c31b.png" alt="Time Progress Panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Other Datasources?
&lt;/h2&gt;

&lt;p&gt;You can probably do something similar with other datasources, but there are too many to test.&lt;/p&gt;

&lt;p&gt;If you use NodeExporter or Pushgateway, you could create your own custom metrics. PostgreSQL can handle pretty complex SQL, so you could probably calculate it there too (though setting up PostgreSQL just for this might be overkill).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This article walks through how to visualize the progress of year, month, and day using Grafana + Prometheus.&lt;/p&gt;

&lt;p&gt;Writing these queries in a DSL like PromQL was a fun little puzzle.&lt;/p&gt;

&lt;p&gt;If you try this setup or come up with a cleaner approach, I'd love to hear about it!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus: &lt;a href="https://prometheus.io/docs/prometheus/latest/querying/functions/" rel="noopener noreferrer"&gt;https://prometheus.io/docs/prometheus/latest/querying/functions/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Changelog
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;2025/11/30: First version.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>grafana</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Understanding Timestamp Difference between shutdown and systemctl poweroff</title>
      <dc:creator>mkt</dc:creator>
      <pubDate>Wed, 22 Oct 2025 09:48:21 +0000</pubDate>
      <link>https://dev.to/mkt/understanding-timestamp-difference-between-shutdown-and-systemctl-poweroff-4a5l</link>
      <guid>https://dev.to/mkt/understanding-timestamp-difference-between-shutdown-and-systemctl-poweroff-4a5l</guid>
      <description>&lt;p&gt;&lt;em&gt;(This is the English translation of my original Japanese post at &lt;a href="https://zenn.dev/md_irohas/articles/343351fac096e3" rel="noopener noreferrer"&gt;Zenn&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I ran into trouble because I didn't properly understand the difference in time formats between the Linux &lt;code&gt;shutdown&lt;/code&gt; command and the &lt;code&gt;systemctl poweroff&lt;/code&gt; family (same applies to &lt;code&gt;systemctl halt&lt;/code&gt; and &lt;code&gt;systemctl reboot&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;As a reminder to myself, here's a concise summary of each time format and how they differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;shutdown -P 06:00&lt;/code&gt;
-&amp;gt; (On Ubuntu,) this means the next 6:00. If it's before 6:00 now, that's today at 6:00; if it's already past 6:00, it's tomorrow at 6:00.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;systemctl poweroff --when=06:00&lt;/code&gt;
-&amp;gt; Today at 6:00; if it's already past that time, it executes immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More examples are in the latter half.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu Server 24.04 (systemd 255)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My mistake
&lt;/h2&gt;

&lt;p&gt;When managing servers, you'll sometimes want to schedule a shutdown for planned power outages, etc.&lt;/p&gt;

&lt;p&gt;The other day, when I tried to run the &lt;code&gt;shutdown&lt;/code&gt; command on Ubuntu 24.04, I saw this warning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;shutdown &lt;span class="nt"&gt;--help&lt;/span&gt;
... omitted ...

This is a compatibility interface, please use the more powerful &lt;span class="s1"&gt;'systemctl reboot'&lt;/span&gt;,
&lt;span class="s1"&gt;'systemctl poweroff'&lt;/span&gt;, &lt;span class="s1"&gt;'systemctl reboot'&lt;/span&gt; commands instead.

&lt;span class="c"&gt;# 'systemctl reboot' appears twice... 🤔&lt;/span&gt;
&lt;span class="c"&gt;# It's fixed in the latest systemd source.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ah, so even &lt;code&gt;shutdown&lt;/code&gt; is unified by systemd.&lt;/p&gt;

&lt;p&gt;So I checked systemctl's man page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poweroff
    ... omitted ...
    This command honors --force and --when= in a similar way as halt.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I can use the &lt;code&gt;--when&lt;/code&gt; option for scheduling.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;code&gt;--when&lt;/code&gt; option description:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--when=
    When used with halt, poweroff, reboot, or kexec, schedule the action
    to be performed at the given timestamp, which should adhere to the
    syntax documented in systemd.time(7) section "PARSING TIMESTAMPS".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't feel like reading all of that, so I quickly asked Copilot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(The original chat is in Japanese)&lt;/p&gt;

&lt;p&gt;Me:&lt;br&gt;
Tell me how to write --when option of systemctl poweroff&lt;/p&gt;

&lt;p&gt;Copilot:&lt;br&gt;
The --when option in the systemctl poweroff command is used to specify when to power off the system.&lt;/p&gt;

&lt;p&gt;Basic syntax&lt;br&gt;
sudo systemctl poweroff --when=&lt;time&gt;&lt;/time&gt;&lt;/p&gt;

&lt;p&gt;Common options&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;now: Power off immediately&lt;/li&gt;
&lt;li&gt;reboot: Power off on the next reboot&lt;/li&gt;
&lt;li&gt;shutdown: Power off on the next system shutdown&lt;/li&gt;
&lt;li&gt;Specific time (e.g. 12:30): Power off at the specified time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples&lt;br&gt;
sudo systemctl poweroff --when=now&lt;br&gt;
→ Power off immediately&lt;br&gt;
sudo systemctl poweroff --when=20:00&lt;br&gt;
→ Power off at 20:00 today&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I thought, okay, same as the &lt;code&gt;shutdown&lt;/code&gt; command (THIS WAS THE MISTAKE. Btw, what is reboot or shutdown at a specified time?).&lt;br&gt;
Indeed, the actual &lt;code&gt;shutdown&lt;/code&gt; command is a symbolic link to &lt;code&gt;systemctl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I assumed that -- just like &lt;code&gt;shutdown&lt;/code&gt; -- if I specify the time as &lt;code&gt;06:00&lt;/code&gt;, it would schedule it for 06:00 the next day, and I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl poweroff &lt;span class="nt"&gt;--when&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"06:00"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit Enter, then...&lt;/p&gt;

&lt;p&gt;It powered off immediately. 😇&lt;/p&gt;

&lt;p&gt;It was just a personal desktop I use casually, so no real harm was done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What went wrong?
&lt;/h2&gt;

&lt;p&gt;Let's read the &lt;code&gt;systemd.time&lt;/code&gt; man page section "PARSING TIMESTAMPS."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;... omitted ...

Examples &lt;span class="k"&gt;for &lt;/span&gt;valid timestamps and their normalized form &lt;span class="o"&gt;(&lt;/span&gt;assuming the current &lt;span class="nb"&gt;time &lt;/span&gt;was 2012-11-23 18:15:22 and the timezone was UTC+8, &lt;span class="k"&gt;for &lt;/span&gt;example &lt;span class="s2"&gt;"TZ=:Asia/Shanghai"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:

      Fri 2012-11-23 11:12:13 -&amp;gt; Fri 2012-11-23 11:12:13
      2012-11-23 11:12:13 -&amp;gt; Fri 2012-11-23 11:12:13
      2012-11-23 11:12:13 UTC -&amp;gt; Fri 2012-11-23 19:12:13
      2012-11-23T11:12:13Z -&amp;gt; Fri 2012-11-23 19:12:13
      2012-11-23T11:12+02:00 -&amp;gt; Fri 2012-11-23 17:12:00
      2012-11-23 -&amp;gt; Fri 2012-11-23 00:00:00
      12-11-23 -&amp;gt; Fri 2012-11-23 00:00:00
      11:12:13 -&amp;gt; Fri 2012-11-23 11:12:13
      11:12 -&amp;gt; Fri 2012-11-23 11:12:00    &amp;lt;- here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you specify only a time, the date is filled in as "today."&lt;br&gt;
If that time has already passed, the action happens immediately.&lt;/p&gt;

&lt;p&gt;A bit unfriendly.&lt;/p&gt;
&lt;h2&gt;
  
  
  How shutdown and systemctl poweroff handle times
&lt;/h2&gt;
&lt;h3&gt;
  
  
  shutdown
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shutdown &lt;span class="o"&gt;[&lt;/span&gt;OPTIONS...] &lt;span class="o"&gt;[&lt;/span&gt;TIME] &lt;span class="o"&gt;[&lt;/span&gt;WALL...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;TIME can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;now&lt;/code&gt;: immediately
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+n&lt;/code&gt;: n minutes from now
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hh:mm&lt;/code&gt;: the next occurrence of hh:mm (24-hour format). For example, 06:30 means the next 06:30 (this works on Ubuntu; other distros may differ).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also note that the &lt;code&gt;shutdown&lt;/code&gt; command can't specify a date.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# If you specify nothing, it's 1 minute later&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;shutdown &lt;span class="nt"&gt;-P&lt;/span&gt;

&lt;span class="c"&gt;# Immediate&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;shutdown &lt;span class="nt"&gt;-P&lt;/span&gt; now

&lt;span class="c"&gt;# The next 06:30 (uses the server's time zone)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;shutdown &lt;span class="nt"&gt;-P&lt;/span&gt; 06:30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  systemctl poweroff
&lt;/h3&gt;

&lt;p&gt;Use the &lt;code&gt;--when&lt;/code&gt; option to specify the time.&lt;/p&gt;

&lt;p&gt;The time format can include not only time (&lt;code&gt;hh:mm&lt;/code&gt;) but also a full datetime and timezone.&lt;/p&gt;

&lt;p&gt;If you specify only a time, the date is completed as "today."&lt;br&gt;
If that time has already passed, it executes immediately.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# If you specify nothing, it's immediate (differs from shutdown)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl poweroff

&lt;span class="c"&gt;# Run at 06:30 today; if already past, run immediately&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl poweroff &lt;span class="nt"&gt;--when&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"06:30"&lt;/span&gt;

&lt;span class="c"&gt;# Run at 06:30 on 2025-10-05&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl poweroff &lt;span class="nt"&gt;--when&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2025-10-05T06:30:00"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be safe, avoid time-only strings; specify a full date and time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;Read the official documentation properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu 22.04 doesn't have the &lt;code&gt;--when&lt;/code&gt; option yet.
&lt;/li&gt;
&lt;li&gt;You can check how timestamps are parsed with &lt;code&gt;systemd-analyze timestamp "06:30"&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;On Ubuntu (and possibly elsewhere), &lt;code&gt;shutdown&lt;/code&gt; is a symlink to &lt;code&gt;systemctl&lt;/code&gt;, but their time formats are not compatible; &lt;code&gt;shutdown&lt;/code&gt; is implemented as a compatibility command inside &lt;code&gt;systemctl&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Change history
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;2025-10-21: Translated from my original Japanese post.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>command</category>
      <category>mistake</category>
    </item>
  </channel>
</rss>
