<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="exp"
     docName="draft-luechow-route86-timestamp-01"
     ipr="trust200902"
     submissionType="independent"
     version="3">
  <front>
    <title abbrev="Route86 Timestamp">Route86: A Compact Context-Dependent Timestamp Format</title>
    <seriesInfo name="Internet-Draft" value="draft-luechow-route86-timestamp-01"/>
    <author initials="T." surname="Lüchow" fullname="Thomas Lüchow">
      <organization>Dorfzwockel</organization>
      <address>
        <email>dorfzwockel@not4bflu55.de</email>
      </address>
    </author>
    <date year="2026" month="August" day="24"/>
    <abstract>
      <t>This document specifies Route86, a compact textual timestamp format for constrained message transports. A Route86 value consists of a three-character Base36 calendar-day component and a three-digit decimal time-of-day component. The canonical representation occupies exactly six ASCII characters.</t>
      <t>The calendar component is interpreted relative to an external reference date. The reference date itself encodes as <tt>AAA</tt>. The time-of-day component divides a fixed BMT day, defined here as UTC+01:00 without daylight-saving adjustment, into 1000 intervals of 86.4 seconds.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro" numbered="true">
      <name>Introduction</name>
      <t>Conventional textual timestamps can be large relative to the payload of constrained transports. Route86 defines a six-character representation that deliberately exchanges universal self-description for compactness.</t>
      <t>Interpretation requires a reference date known to both encoder and decoder. That reference date is external to the six-character value and may be fixed by an application profile, derived from registration context, or otherwise selected by the communicating parties.</t>
      <t>Route86 is not a replacement for a general Internet timestamp format. It is intended for contexts in which compactness, a shared reference context, and approximately minute-scale time resolution are acceptable.</t>
    </section>

    <section anchor="requirements" numbered="true">
      <name>Requirements Language</name>
      <t>The key words <bcp14>MUST</bcp14>, <bcp14>MUST NOT</bcp14>, <bcp14>REQUIRED</bcp14>, <bcp14>SHALL</bcp14>, <bcp14>SHALL NOT</bcp14>, <bcp14>SHOULD</bcp14>, <bcp14>SHOULD NOT</bcp14>, <bcp14>RECOMMENDED</bcp14>, <bcp14>NOT RECOMMENDED</bcp14>, <bcp14>MAY</bcp14>, and <bcp14>OPTIONAL</bcp14> in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
    </section>

    <section anchor="format" numbered="true">
      <name>Timestamp Format</name>
      <t>A canonical Route86 timestamp consists of exactly six ASCII characters:</t>
      <artwork><![CDATA[
DDDBBB
]]></artwork>
      <t><tt>DDD</tt> is the calendar-day component. <tt>BBB</tt> is the time-of-day component. No separator occurs between them.</t>
      <t>The syntax is described using ABNF <xref target="RFC5234"/>:</t>
      <sourcecode type="abnf"><![CDATA[
route86        = day-component beat-component
day-component = 3base36
beat-component = 3DIGIT
base36         = DIGIT / %x41-5A
]]></sourcecode>
      <t>The <tt>base36</tt> rule admits only ASCII digits and uppercase ASCII letters <tt>A</tt> through <tt>Z</tt>. Thus the ABNF describes canonical values only.</t>
    </section>

    <section anchor="temporal-reference" numbered="true">
      <name>Temporal Reference and BMT Normalization</name>
      <t>Route86 evaluates both the calendar day and the time of day in a single common reference offset. This document defines that offset as UTC+01:00, corresponding to Biel Mean Time (BMT) as used by Internet Time <xref target="SWATCH"/>.</t>
      <t>BMT in Route86 is a fixed offset. Daylight-saving time is not applied.</t>
      <t>An encoder receiving an instant expressed in another offset <bcp14>MUST</bcp14> first convert that instant to UTC+01:00. The BMT civil date produced by that conversion is used for <tt>DDD</tt>, and the BMT time of day from the same conversion is used for <tt>BBB</tt>.</t>
      <t>If an input value does not identify an absolute instant, for example because it contains a local clock time without an offset or equivalent timezone context, an application profile <bcp14>MUST</bcp14> supply the missing context before Route86 encoding.</t>
    </section>

    <section anchor="reference-date" numbered="true">
      <name>Reference Date</name>
      <t>The Route86 calendar component is relative to a reference date that is external to the six-character timestamp. A receiver <bcp14>MUST</bcp14> know the applicable reference date before interpreting <tt>DDD</tt>.</t>
      <t>The reference date is a civil date in the proleptic Gregorian calendar as observed in BMT. It has no time-of-day component.</t>
      <t>This document uses <tt>1970-01-01</tt> as the reference date in examples. Applications <bcp14>MAY</bcp14> use another reference date.</t>
      <t>The reference date itself has a day difference of zero and therefore encodes as <tt>AAA</tt>. Calendar-day counting is not inclusive.</t>
    </section>

    <section anchor="calendar" numbered="true">
      <name>Calendar-Day Component</name>
      <t>Let <tt>target_date</tt> be the BMT civil date obtained after the normalization in <xref target="temporal-reference"/>. Let <tt>reference_date</tt> be the shared Route86 reference date.</t>
      <t>The signed calendar-day difference is:</t>
      <artwork><![CDATA[
day_delta = target_date - reference_date
]]></artwork>
      <t>The subtraction is the difference in proleptic-Gregorian ordinal dates. Consequently, the reference date has <tt>day_delta = 0</tt>, the immediately preceding date has <tt>day_delta = -1</tt>, and the immediately following date has <tt>day_delta = 1</tt>.</t>
      <t>Route86 then applies the decimal offset 13330:</t>
      <artwork><![CDATA[
route86_day = day_delta + 13330
]]></artwork>
      <t>The value 13330 is chosen because:</t>
      <artwork><![CDATA[
AAA(base36) = 13330(decimal)
]]></artwork>
      <t><tt>route86_day</tt> <bcp14>MUST</bcp14> be in the inclusive range 0 through 46655. Values outside that range are not representable by this version of Route86 and <bcp14>MUST</bcp14> be rejected.</t>
      <t>The corresponding representable <tt>day_delta</tt> range is therefore -13330 through +33325 days.</t>
      <t>The integer <tt>route86_day</tt> is encoded in Base36 using the alphabet:</t>
      <artwork><![CDATA[
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
]]></artwork>
      <t>The result <bcp14>MUST</bcp14> be left-padded with <tt>0</tt> characters to exactly three characters. Encoders <bcp14>MUST</bcp14> emit uppercase ASCII letters.</t>
    </section>

    <section anchor="beat" numbered="true">
      <name>Time-of-Day Component</name>
      <t>Route86 divides each nominal BMT day into 1000 equal intervals. Each interval is 86.4 seconds long.</t>
      <t>Let <tt>s</tt> be the exact number of elapsed seconds since BMT midnight, including any fractional part, with:</t>
      <artwork><![CDATA[
0 <= s < 86400
]]></artwork>
      <t>The beat number is:</t>
      <artwork><![CDATA[
beat = floor(s * 1000 / 86400)
]]></artwork>
      <t>This is equivalent to <tt>floor(s / 86.4)</tt>. The mathematical floor operation is normative. Implementations <bcp14>SHOULD</bcp14> avoid binary floating-point boundary errors, for example by using integer or rational arithmetic when the source timestamp provides subsecond precision.</t>
      <t>The result is an integer in the range 0 through 999 and <bcp14>MUST</bcp14> be encoded as exactly three decimal digits, left-padded with zeroes as necessary.</t>
      <artwork><![CDATA[
0   -> 000
7   -> 007
42  -> 042
382 -> 382
999 -> 999
]]></artwork>
      <t>The commercial <tt>@</tt> notation associated with Internet Time is not part of Route86.</t>

      <section anchor="leap-seconds" numbered="true">
        <name>Leap Seconds</name>
        <t>Route86 models a nominal day as exactly 86400 seconds and has no distinct lexical representation for a leap-second label such as <tt>23:59:60</tt>.</t>
        <t>An encoder presented with a timestamp containing a leap-second label <bcp14>MUST NOT</bcp14> encode that label directly. The application <bcp14>MAY</bcp14> normalize such an input before Route86 encoding if its profile defines an unambiguous mapping. Applications that need to preserve leap-second identity <bcp14>MUST NOT</bcp14> rely on Route86 as their sole timestamp representation.</t>
      </section>
    </section>

    <section anchor="encoding" numbered="true">
      <name>Encoding Algorithm</name>
      <t>Given an absolute input instant and a shared reference date, an encoder performs the following steps:</t>
      <ol spacing="normal" type="1">
        <li>Convert the input instant to the fixed offset UTC+01:00 (BMT).</li>
        <li>Extract the BMT civil date and the exact elapsed seconds since BMT midnight.</li>
        <li>Compute <tt>day_delta</tt> as the BMT target date minus the reference date.</li>
        <li>Compute <tt>route86_day = day_delta + 13330</tt>. Reject the input if the value is outside 0 through 46655.</li>
        <li>Encode <tt>route86_day</tt> as three uppercase Base36 characters, left-padding with <tt>0</tt> when needed.</li>
        <li>Compute <tt>beat = floor(s * 1000 / 86400)</tt>.</li>
        <li>Encode <tt>beat</tt> as three decimal digits, left-padding with <tt>0</tt> when needed.</li>
        <li>Concatenate the two components without a separator.</li>
      </ol>
    </section>

    <section anchor="decoding" numbered="true">
      <name>Decoding Algorithm</name>
      <t>Given a canonical Route86 value and the applicable reference date, a decoder performs the following steps:</t>
      <ol spacing="normal" type="1">
        <li>Validate the six-character grammar in <xref target="format"/>.</li>
        <li>Decode <tt>DDD</tt> as an unsigned Base36 integer <tt>route86_day</tt>.</li>
        <li>Compute <tt>day_delta = route86_day - 13330</tt>.</li>
        <li>Add <tt>day_delta</tt> Gregorian calendar days to the reference date to obtain the BMT civil date.</li>
        <li>Decode <tt>BBB</tt> as decimal integer <tt>beat</tt>.</li>
        <li>Interpret the time component as the half-open interval beginning at <tt>beat * 86.4</tt> seconds after BMT midnight and ending at <tt>(beat + 1) * 86.4</tt> seconds after BMT midnight.</li>
      </ol>
      <t>For <tt>beat = 999</tt>, the end of the half-open interval is the following BMT midnight.</t>
      <t>Route86 does not define a representative point within the decoded interval. An application that needs one, such as the interval start or midpoint, <bcp14>MUST</bcp14> define that convention separately.</t>
    </section>

    <section anchor="canonical" numbered="true">
      <name>Canonical Representation</name>
      <t>A canonical Route86 timestamp:</t>
      <ul spacing="normal">
        <li><bcp14>MUST</bcp14> contain exactly six ASCII characters;</li>
        <li><bcp14>MUST</bcp14> contain three Base36 characters followed by three decimal digits;</li>
        <li><bcp14>MUST</bcp14> use uppercase letters in the Base36 component;</li>
        <li><bcp14>MUST NOT</bcp14> contain whitespace or separators;</li>
        <li><bcp14>MUST NOT</bcp14> contain an <tt>@</tt> character; and</li>
        <li><bcp14>SHOULD</bcp14> be transported and stored as an opaque six-character string.</li>
      </ul>
      <t>Protocol decoders <bcp14>MUST</bcp14> reject characters outside the grammar. User-interface implementations <bcp14>MAY</bcp14> accept lowercase letters for convenience, but such input is non-canonical and <bcp14>MUST</bcp14> be converted to uppercase before storage, comparison, or protocol use.</t>
      <t>The following value is canonical:</t>
      <artwork><![CDATA[
Q8S382
]]></artwork>
      <t>The following values are not canonical:</t>
      <artwork><![CDATA[
q8s382
Q8S@382
Q8S-382
Q8S 382
]]></artwork>
    </section>

    <section anchor="vectors" numbered="true">
      <name>Test Vectors</name>
      <t>This section is normative with respect to the arithmetic demonstrated by the vectors.</t>

      <section anchor="day-vectors" numbered="true">
        <name>Calendar-Day Vectors</name>
        <t>Using the reference date <tt>1970-01-01</tt>:</t>
        <table align="left">
          <name>Calendar-day vectors</name>
          <thead>
            <tr><th>Target BMT date</th><th>day_delta</th><th>Decimal value</th><th>DDD</th></tr>
          </thead>
          <tbody>
            <tr><td>1933-07-04</td><td>-13330</td><td>0</td><td>000</td></tr>
            <tr><td>1969-12-31</td><td>-1</td><td>13329</td><td>AA9</td></tr>
            <tr><td>1970-01-01</td><td>0</td><td>13330</td><td>AAA</td></tr>
            <tr><td>1970-01-02</td><td>1</td><td>13331</td><td>AAB</td></tr>
            <tr><td>2026-08-17</td><td>20682</td><td>34012</td><td>Q8S</td></tr>
            <tr><td>2061-03-29</td><td>33325</td><td>46655</td><td>ZZZ</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="beat-vectors" numbered="true">
        <name>Time-of-Day Vectors</name>
        <table align="left">
          <name>BMT beat vectors</name>
          <thead>
            <tr><th>BMT time</th><th>Elapsed seconds</th><th>BBB</th></tr>
          </thead>
          <tbody>
            <tr><td>00:00:00</td><td>0</td><td>000</td></tr>
            <tr><td>00:01:26.399</td><td>86.399</td><td>000</td></tr>
            <tr><td>00:01:26.400</td><td>86.4</td><td>001</td></tr>
            <tr><td>09:10:10</td><td>33010</td><td>382</td></tr>
            <tr><td>23:59:59</td><td>86399</td><td>999</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="complete-vector" numbered="true">
        <name>Complete Example</name>
        <t>With reference date <tt>1970-01-01</tt>, the instant <tt>2026-08-17T10:10:10+02:00</tt> first normalizes to <tt>2026-08-17T09:10:10+01:00</tt> BMT.</t>
        <artwork><![CDATA[
Reference date:      1970-01-01
Input instant:       2026-08-17T10:10:10+02:00
BMT instant:         2026-08-17T09:10:10+01:00
day_delta:           20682
route86_day:         34012
DDD:                 Q8S
BBB:                 382
Route86 timestamp:   Q8S382
Encoded length:      6 octets
]]></artwork>
      </section>
    </section>

    <section anchor="message-entities" numbered="true">
      <name>Use in Message Entities</name>
      <t>A Route86 timestamp <bcp14>MAY</bcp14> be used as the temporal component of a message entity or identifier.</t>
      <t>A Route86 value <bcp14>MUST NOT</bcp14> be assumed to be globally unique. Applications requiring uniqueness <bcp14>MUST</bcp14> combine it with additional context, such as an origin identifier, recipient identifier, nonce, sequence value, or cryptographic identifier.</t>
      <t>A tuple consisting of origin context, recipient context, and Route86 value is one possible application-level construction, but this document does not standardize such a tuple.</t>
    </section>

    <section anchor="precision-ordering" numbered="true">
      <name>Precision, Intervals, and Ordering</name>
      <t>The time-of-day component has a nominal resolution of 86.4 seconds. Route86 <bcp14>MUST NOT</bcp14> be used as the sole representation where second-level timestamp precision is required.</t>
      <t>Within one shared reference-date context, canonical Route86 strings sort chronologically in ascending ASCII lexicographic order. This follows from the fixed-width Base36 day component, the value order of the canonical Base36 alphabet, and the fixed-width decimal beat component.</t>
      <t>This ordering property does not apply across values interpreted with different reference dates.</t>
    </section>

    <section anchor="profiles" numbered="true">
      <name>Application Profiles and Salted Reference Dates</name>
      <t>An application profile <bcp14>MAY</bcp14> select a fixed reference date, negotiate a reference date, derive it from registration state, or use a salted reference date.</t>
      <t>A profile that does not use a universally fixed reference date <bcp14>SHOULD</bcp14> specify how the date is established, how long it remains valid, and what happens when a target date falls outside the representable Route86 range.</t>
      <t>Policies that restrict the age or placement of a reference date are application-level rules and are not part of the Route86 wire format.</t>
    </section>

    <section anchor="security" numbered="true">
      <name>Security Considerations</name>
      <t>Route86 is an encoding format. It provides no confidentiality, integrity, authentication, authorization, or replay protection.</t>
      <t>A salted reference date can obscure casual interpretation of a timestamp, but it <bcp14>MUST NOT</bcp14> be treated as a cryptographic secret or security boundary. Candidate date ranges are commonly small enough to permit exhaustive guessing, especially when an attacker has approximate knowledge of the encoded date.</t>
      <t>Protocols requiring authenticated or integrity-protected timestamps <bcp14>MUST</bcp14> provide those properties independently of Route86.</t>
      <t>Implementations comparing Route86 values from untrusted sources <bcp14>MUST</bcp14> ensure that the same reference-date context applies before relying on chronological ordering.</t>
    </section>

    <section anchor="iana" numbered="true">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>Normative References</name>
      <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author initials="S." surname="Bradner" fullname="Scott Bradner"/>
          <date month="March" year="1997"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>

      <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author initials="B." surname="Leiba" fullname="Barry Leiba"/>
          <date month="May" year="2017"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>

      <reference anchor="RFC5234" target="https://www.rfc-editor.org/info/rfc5234">
        <front>
          <title>Augmented BNF for Syntax Specifications: ABNF</title>
          <author initials="D." surname="Crocker" fullname="Dave Crocker"/>
          <author initials="P." surname="Overell" fullname="Paul Overell"/>
          <date month="January" year="2008"/>
        </front>
        <seriesInfo name="STD" value="68"/>
        <seriesInfo name="RFC" value="5234"/>
        <seriesInfo name="DOI" value="10.17487/RFC5234"/>
      </reference>
    </references>

    <references>
      <name>Informative References</name>
      <reference anchor="RFC3339" target="https://www.rfc-editor.org/info/rfc3339">
        <front>
          <title>Date and Time on the Internet: Timestamps</title>
          <author initials="G." surname="Klyne" fullname="Graham Klyne"/>
          <author initials="C." surname="Newman" fullname="Chris Newman"/>
          <date month="July" year="2002"/>
        </front>
        <seriesInfo name="RFC" value="3339"/>
        <seriesInfo name="DOI" value="10.17487/RFC3339"/>
      </reference>

      <reference anchor="SWATCH" target="https://www.swatch.com/en-en/internet-time.html">
        <front>
          <title>Internet Time</title>
          <author>
            <organization>Swatch AG</organization>
          </author>
          <date/>
        </front>
        <refcontent>Defines the 1000-beat day and identifies BMT as the reference for Internet Time.</refcontent>
      </reference>
    </references>

    <section anchor="changes" numbered="true">
      <name>Changes from -00</name>
      <ul spacing="normal">
        <li>Clarified that the reference date itself has <tt>day_delta = 0</tt> and encodes as <tt>AAA</tt>.</li>
        <li>Defined calendar arithmetic explicitly and established the full representable range <tt>000</tt> through <tt>ZZZ</tt>.</li>
        <li>Specified that both timestamp components are derived after normalization to fixed UTC+01:00 BMT.</li>
        <li>Defined the beat calculation using normative mathematical floor semantics.</li>
        <li>Specified leap-second behavior.</li>
        <li>Added ABNF, explicit encoding and decoding algorithms, and normative test vectors.</li>
        <li>Corrected the complete example from <tt>Q8T340</tt> to <tt>Q8S382</tt>.</li>
        <li>Clarified that canonical values sort chronologically only within a shared reference-date context.</li>
        <li>Separated application-profile policy from the Route86 wire format.</li>
        <li>Expanded security considerations and references.</li>
        <li>Updated the author's email address.</li>
      </ul>
    </section>
  </back>
</rfc>
