---
title: "Before NTP, network time fit in four bytes"
locale: "en"
url: "https://irz.fr/en/articles/before-ntp-four-byte-time-en"
markdown_url: "https://irz.fr/en/articles/before-ntp-four-byte-time-en.md"
category: "tech"
tags: ["networking", "NTP", "RFC", "time", "protocols"]
published_at: "2026-08-31T09:02:00.000Z"
author: "Camille Morel"
translation: "https://irz.fr/fr/articles/avant-ntp-quatre-octets-heure-fr.md"
---

# Before NTP, network time fit in four bytes

RFC 868 answered with 32 bits: seconds since 1900. The protocol was tiny because it omitted latency, uncertainty and even the fractional second that NTP would later need to measure.

On August 30, 2026, Jeff Geerling connected old Macs to a network service simple enough to fit in nearly one sentence: open **port 37**, receive four bytes, close.[1](https://www.jeffgeerling.com/blog/2026/rfc-867-868-time/)

Those bytes are one unsigned 32-bit integer, the number of seconds since midnight on January 1, 1900,[3](https://www.rfc-editor.org/rfc/rfc868.html) with no JSON, timezone, server identifier, latency measurement or even a fractional second attached to the answer.

In 1983, RFC 868 simply called it **Time**.[3](https://www.rfc-editor.org/rfc/rfc868.html)

Its size is charming now, enough to suggest an age when protocols knew when to stop, but the more useful explanation is prosaic: the four-byte reply stays tiny because the protocol **solves a deliberately narrow part of the problem**.

NTP would appear two years later carrying much of what those four bytes could not express.[4](https://www.rfc-editor.org/rfc/rfc958.html)

## Two services

RFC 867 and RFC 868 were both published in May 1983, offering two quite different answers to the same need. **Daytime**, RFC 867, listens on port 13. Over TCP the server sends one line containing date and time and closes the connection; over UDP an incoming datagram triggers a reply.[2](https://www.rfc-editor.org/rfc/rfc867.html)

The document would probably unsettle a modern API designer because **there is no required syntax**;[2](https://www.rfc-editor.org/rfc/rfc867.html) it recommends a single printable ASCII line and gives two popular formats, yet a client cannot safely assume either one. Daytime is primarily a human debugging and measurement tool.[2](https://www.rfc-editor.org/rfc/rfc867.html)

RFC 867 says so itself: for machine-useful time, use RFC 868.[2](https://www.rfc-editor.org/rfc/rfc867.html)

Time gives up that readability in exchange for a deterministic machine reply: over TCP the client connects to port 37, receives a 32-bit value and disconnects, while over UDP an empty datagram is enough to trigger the four-byte response.[3](https://www.rfc-editor.org/rfc/rfc868.html)

> **1983: two answers to the same need**
> - Daytime · one ASCII line, human readable, deliberately unspecified syntax: Port 13
> - Time · 32 binary bits, seconds since January 1 1900: Port 37
> - Daytime reads directly; Time parses without negotiating a text format: Benefit
> - neither service measures what the network adds between server and client: Shared gap
> RFC 867 and RFC 868 already separate human display from machine representation.

## Four bytes

RFC 868 chooses an epoch that NTP later inherits: **00:00:00 on January 1, 1900**.[3](https://www.rfc-editor.org/rfc/rfc868.html)

January 1, 1970 therefore has the value **2,208,988,800**.[3](https://www.rfc-editor.org/rfc/rfc868.html) Converting a Time value to the Unix epoch can subtract exactly that many seconds, which is what Geerling does in his 2026 demonstration.[1](https://www.jeffgeerling.com/blog/2026/rfc-867-868-time/)

The protocol has one-second resolution because its counter stores whole seconds,[3](https://www.rfc-editor.org/rfc/rfc868.html) a trade-off that fits the motivation in the RFC: some systems have no date/time clock, while all clocks remain vulnerable to human or machine error. A brief poll of several independent network sites can at least confirm or correct a machine's local idea of time.[3](https://www.rfc-editor.org/rfc/rfc868.html)

> **RFC 868: the entire reply fits in 32 bits**
> Diagram of an empty request to port 37 and a four-byte reply representing seconds since 1900
> - PORT 37 · ONE REQUEST, FOUR BYTES
> - CLIENT
empty UDP
> - port 37
> - SERVER
local time
> - 32 bits · seconds since 1900
> - The reply contains server time. It contains no information about the journey taken by that reply.
> The UDP service defined by RFC 868 receives an empty datagram and returns exactly one 32-bit integer.

Four bytes are perfectly sufficient if three assumptions hold: whole-second granularity is enough, network transit is negligible for the application, and the client already knows how to interpret the 1900 epoch.

The protocol looks naive only when asked to solve more than its contract promises; its design is mainly **narrow**.

## Missing journey

Suppose a server stamps its reply at 12:00:00 and the packet reaches the client 400 ms later.

RFC 868 gives the client “12:00:00” without any way to know whether the reply spent 2 ms, 40 ms or 400 ms travelling, because the packet carries no request-departure timestamp, server-receive timestamp or reply-departure timestamp.

Even a returned value with microsecond resolution would not reveal exact local time at reception, because a more precise number still says nothing about how long the packet spent travelling.

That is the important difference between **resolution** and **synchronization**.

Geerling runs into the same boundary naturally while replaying the protocol on a contemporary network: Time is excellent for showing network time on a vintage machine, but contains no mechanism for compensating variable delays across a multi-hop Internet.[1](https://www.jeffgeerling.com/blog/2026/rfc-867-868-time/)

The small packet has not eliminated the problem; it has moved the problem into the client and into assumptions about the path.

## Four timestamps

The first RFC actually titled **Network Time Protocol** is RFC 958 from September **1985**, not 1988;[4](https://www.rfc-editor.org/rfc/rfc958.html) RFC 1059 from July 1988 is the **NTP version 1** specification that supersedes it.[5](https://www.rfc-editor.org/rfc/rfc1059.html) The distinction is minor historically but useful if the evolution from Time to NTP is going to be described precisely.

RFC 958 explicitly says NTP evolved from the Time Protocol and ICMP Timestamp messages.[4](https://www.rfc-editor.org/rfc/rfc958.html)

The conceptual jump appears in four instants:

- **t1**: request leaves the client;
- **t2**: request reaches the server;
- **t3**: reply leaves the server;
- **t4**: reply reaches the client.[4](https://www.rfc-editor.org/rfc/rfc958.html)

Those four numbers let the client estimate both round-trip network delay and its clock offset relative to the server. RFC 958 already gives equations recognizably equivalent to modern NTP.[4](https://www.rfc-editor.org/rfc/rfc958.html)

> **NTP adds what Time could not observe**
> Diagram showing NTP timestamps t1 t2 t3 t4 between client and server and calculations for delay and offset
> - FOUR TIMESTAMPS TO MEASURE THE NETWORK
> - CLIENT
> - SERVER
> - T1
> - T2
> - T3
> - T4
> - delay = (T4−T1) − (T3−T2)
> - offset ≈ [(T2−T1) + (T3−T4)] / 2
> NTP no longer merely transmits a clock reading; it observes the times around the journey so clock and network can be separated as far as the model permits.

The calculation still depends on a real assumption: forward and return delays must be symmetric enough for the estimate to remain useful, and strong path asymmetry can still bias it.[4](https://www.rfc-editor.org/rfc/rfc958.html)

The protocol now at least carries the measurements needed to talk about the network rather than pretending it has no duration.

## Thirty-two plus thirty-two

NTP in 1985 already uses **64-bit timestamps**,[4](https://www.rfc-editor.org/rfc/rfc958.html) with the upper half storing seconds relative to 1900 and the lower half storing a 32-bit fraction of a second. Its least-significant fraction bit corresponds to roughly 0.23 ns of numerical resolution.[4](https://www.rfc-editor.org/rfc/rfc958.html)

That numerical resolution says nothing about a 1985 machine actually synchronizing to 0.23 ns; timestamp granularity and the accuracy of a real clock-synchronization system live at different layers.

NTP also carries information about local clock precision, estimated error, drift and reference source.[4](https://www.rfc-editor.org/rfc/rfc958.html) Later versions develop clock selection, filtering and discipline; NTPv4 formalizes statistics including offset, delay, dispersion and jitter.[6](https://www.rfc-editor.org/rfc/rfc5905.html)

Where RFC 868 gains simplicity by omitting context, NTP transports enough context to decide **how much confidence to place in a received time**.

## February 7

RFC 868's 32-bit seconds counter has a mathematical deadline: after 4,294,967,295 seconds, no larger unsigned value fits in the field. The next second corresponds to **06:28:16 UTC on February 7, 2036**.[7](https://www.rfc-editor.org/rfc/rfc4330.html)

RFC 868 already warned in 1983 that its epoch would “serve until the year 2036.”[3](https://www.rfc-editor.org/rfc/rfc868.html)

NTP inherits the same 32-bit seconds field inside its 64-bit timestamp. The fractional half increases resolution; it does not extend the range of the seconds counter.

Modern specifications therefore use **NTP eras**. RFC 4330 explains that a timestamp after rollover can be interpreted relative to a new base beginning exactly at 06:28:16 UTC on February 7, 2036.[7](https://www.rfc-editor.org/rfc/rfc4330.html) RFC 5905 formalizes era 0 and era 1 around the wrap.[6](https://www.rfc-editor.org/rfc/rfc5905.html)

> **The same 1900 epoch crosses three generations**
> - RFC 868: 32 seconds bits on port 37: 1983
> - RFC 958: NTP adds fractions, timestamps, error and delay: 1985
> - NTPv4 formalizes selection, offset, delay, dispersion and eras: 2010
> - seconds wrap to zero; era provides the missing context: 2036
> The rollover was not a surprise discovered later: RFC 868 already states the 2036 limit in 1983.

Context therefore becomes mandatory, because the seconds field alone can no longer distinguish 1900 from 2036.

There is a pleasing reversal here: the protocol that gained elegance from one self-contained integer eventually needs outside information to stay unambiguous beyond its first 136-year window.

## Several clocks

RFC 868 nevertheless contains an idea more sophisticated than its packet: it recommends a brief poll of **several independent sites** to confirm or correct local time.[3](https://www.rfc-editor.org/rfc/rfc868.html)

No consensus mechanism exists inside the packet and strategy is left to the client; NTP gradually turns that intuition into a distributed system. RFC 958 already lets peers expose their clock type, precision, estimated error and drift, then use those properties to choose better references and fall back when a source fails.[4](https://www.rfc-editor.org/rfc/rfc958.html)

NTPv4 goes much further with strata, filtering, clock discipline and procedures for rejecting inconsistent measurements.[6](https://www.rfc-editor.org/rfc/rfc5905.html)

The protocol grows because the question has changed: RFC 868 answers **what time does this server say it is?**, while NTP tries to answer **what estimate of time can we defend after accounting for clocks, network delay and uncertainty?**

## Keep four bytes

None of this makes RFC 868 silly in 2026.

Geerling's demonstration shows exactly why old protocols remain delightful to manipulate: an xinetd service, one port, four bytes visible through `xxd`, and a vintage computer can obtain network time without a contemporary NTP client.[1](https://www.jeffgeerling.com/blog/2026/rfc-867-868-time/)

Inside a closed lab, a test setup, a very constrained device or a teaching demonstration, a narrow protocol may be exactly the right abstraction.

Its usefulness survives as long as those omissions are named rather than mistaken for guarantees.

The lesson of RFC 868 is not that networks should have stayed simple. It is that **protocol size often tracks how much uncertainty the design is willing to leave somewhere else**.

Four bytes are enough to transport a seconds counter; once a client needs to know how long the counter took to arrive, whether its server drifts, whether another clock disagrees, what error is plausible and which side of February 2036 the value belongs to, those four bytes stop being the complete time.

They become what they always were: one measurement surrounded by assumptions that later network protocols learned to write down explicitly.

## References

1. [Jeff Geerling, Before NTP there were Time and Daytime, August 30 2026](https://www.jeffgeerling.com/blog/2026/rfc-867-868-time/)
2. [RFC 867, Daytime Protocol, May 1983](https://www.rfc-editor.org/rfc/rfc867.html)
3. [RFC 868, Time Protocol, May 1983](https://www.rfc-editor.org/rfc/rfc868.html)
4. [RFC 958, Network Time Protocol (NTP), September 1985](https://www.rfc-editor.org/rfc/rfc958.html)
5. [RFC 1059, Network Time Protocol version 1, July 1988](https://www.rfc-editor.org/rfc/rfc1059.html)
6. [RFC 5905, Network Time Protocol Version 4, June 2010](https://www.rfc-editor.org/rfc/rfc5905.html)
7. [RFC 4330, Simple Network Time Protocol Version 4, January 2006](https://www.rfc-editor.org/rfc/rfc4330.html)
