Module 3 · Data, Variables, Samples, and Measurement Lesson 26 of 120
Timestamps, Time Zones, Calendars, and Observation Time
Different clock strings can describe the same instant.
Transcript
23 sentences · select one to jump thereCheck your understanding
Are event time and receipt time interchangeable?
Code lab
Run it yourself
The lesson source in 7 languages. Edit it, run TypeScript and Python right here, and compare with the expected output.
/**
* Fintech Math Bootcamp · Lesson 026 of 120
* Timestamps, Time Zones, Calendars, and Observation Time
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: Different clock strings can describe the same instant
* Rule: event time ≠ receipt time ≠ decision time
*
* Try it: Are event time and receipt time interchangeable?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
export function lesson026() {
const a = Date.parse("2026-01-01T10:00:00Z");
const b = Date.parse("2026-01-01T12:00:00+02:00");
const received = Date.parse("2026-01-01T10:00:05Z");
const result = {sameInstant: a === b,
latencySeconds: (received - a) / 1000};
return result;
}
export const checkedResult = {"sameInstant":true,"latencySeconds":5};
// Run this file directly: npx tsx lessons/03-data-variables-samples-and-measurement/026-timestamps-time-zones-calendars-and-observation-time.ts
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/").split("/").pop()!)) {
console.log(JSON.stringify(lesson026(), null, 2));
}
Your output
Press Run to execute the code in your browser.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}"""
Fintech Math Bootcamp · Lesson 026 of 120
Timestamps, Time Zones, Calendars, and Observation Time
Module 03: Data, Variables, Samples, and Measurement
Scenario: Different clock strings can describe the same instant
Rule: event time ≠ receipt time ≠ decision time
Try it: Are event time and receipt time interchangeable?
Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
Free course: https://courses.thefintechbuilder.com
Synthetic teaching example, not financial advice or a production library.
Run it: python main.py
"""
import json
from datetime import datetime
def parse_instant(text: str) -> datetime:
"""Parses an ISO 8601 timestamp with a Z or +hh:mm offset (fromisoformat reads Z only from 3.11)."""
return datetime.fromisoformat(text.replace("Z", "+00:00"))
def lesson026() -> dict:
a = parse_instant("2026-01-01T10:00:00Z")
b = parse_instant("2026-01-01T12:00:00+02:00")
received = parse_instant("2026-01-01T10:00:05Z")
result = {
"sameInstant": a == b,
"latencySeconds": (received - a).total_seconds(),
}
return result
if __name__ == "__main__":
print(json.dumps(lesson026(), indent=2))
Your output
Press Run to execute the code in your browser.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}/**
* Fintech Math Bootcamp · Lesson 026 of 120
* Timestamps, Time Zones, Calendars, and Observation Time
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: Different clock strings can describe the same instant
* Rule: event time ≠ receipt time ≠ decision time
*
* Try it: Are event time and receipt time interchangeable?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: javac Main.java && java Main
*/
import java.time.OffsetDateTime;
public class Main {
static final class ClockCheck {
final boolean sameInstant;
final double latencySeconds;
ClockCheck(boolean sameInstant, double latencySeconds) {
this.sameInstant = sameInstant;
this.latencySeconds = latencySeconds;
}
}
// Milliseconds since the Unix epoch, like Date.parse.
static long parseInstant(String text) {
return OffsetDateTime.parse(text).toInstant().toEpochMilli();
}
static ClockCheck lesson026() {
long a = parseInstant("2026-01-01T10:00:00Z");
long b = parseInstant("2026-01-01T12:00:00+02:00");
long received = parseInstant("2026-01-01T10:00:05Z");
ClockCheck result = new ClockCheck(a == b, (received - a) / 1000.0);
return result;
}
public static void main(String[] args) {
ClockCheck result = lesson026();
System.out.println(object(
"sameInstant", String.valueOf(result.sameInstant),
"latencySeconds", num(result.latencySeconds)));
}
// Formats a double the way JSON.stringify does: whole numbers without ".0", null for NaN or infinity.
static String num(double x) {
if (Double.isNaN(x) || Double.isInfinite(x)) return "null";
if (x == Math.rint(x) && Math.abs(x) < 1e15) return String.valueOf((long) x);
return String.valueOf(x);
}
static String quote(String text) {
return "\"" + text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
}
// Indents an already formatted JSON value by one level.
static String nested(String json) {
return json.replace("\n", "\n ");
}
static String object(String... keysAndValues) {
if (keysAndValues.length == 0) return "{}";
StringBuilder out = new StringBuilder("{");
for (int i = 0; i < keysAndValues.length; i += 2) {
out.append(i == 0 ? "\n " : ",\n ")
.append(quote(keysAndValues[i])).append(": ").append(nested(keysAndValues[i + 1]));
}
return out.append("\n}").toString();
}
}
No browser runner for Java yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}// Fintech Math Bootcamp · Lesson 026 of 120
// Timestamps, Time Zones, Calendars, and Observation Time
// Module 03: Data, Variables, Samples, and Measurement
//
// Scenario: Different clock strings can describe the same instant
// Rule: event time ≠ receipt time ≠ decision time
//
// Try it: Are event time and receipt time interchangeable?
//
// Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
// Free course: https://courses.thefintechbuilder.com
// Synthetic teaching example, not financial advice or a production library.
//
// Run it: go run main.go
package main
import (
"encoding/json"
"fmt"
"time"
)
type ClockCheck struct {
SameInstant bool `json:"sameInstant"`
LatencySeconds float64 `json:"latencySeconds"`
}
func lesson026() (ClockCheck, error) {
a, err := time.Parse(time.RFC3339, "2026-01-01T10:00:00Z")
if err != nil {
return ClockCheck{}, err
}
b, err := time.Parse(time.RFC3339, "2026-01-01T12:00:00+02:00")
if err != nil {
return ClockCheck{}, err
}
received, err := time.Parse(time.RFC3339, "2026-01-01T10:00:05Z")
if err != nil {
return ClockCheck{}, err
}
result := ClockCheck{
SameInstant: a.Equal(b), // compares instants; == would also compare the zones
LatencySeconds: float64(received.Sub(a).Milliseconds()) / 1000,
}
return result, nil
}
func main() {
result, err := lesson026()
if err != nil {
panic(err)
}
printJSON(result)
}
// printJSON prints a value as JSON indented with two spaces, like JSON.stringify(value, null, 2).
func printJSON(value any) {
out, err := json.MarshalIndent(value, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
No browser runner for Go yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}/**
* Fintech Math Bootcamp · Lesson 026 of 120
* Timestamps, Time Zones, Calendars, and Observation Time
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: Different clock strings can describe the same instant
* Rule: event time ≠ receipt time ≠ decision time
*
* Try it: Are event time and receipt time interchangeable?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: g++ -std=c++17 -o main main.cpp && ./main
*/
#include <charconv>
#include <cmath>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
// Formats a double the way JSON.stringify does: shortest round-trip form, null for NaN or infinity.
std::string num(double x) {
if (!std::isfinite(x)) return "null";
char buffer[32];
auto [end, error] = std::to_chars(buffer, buffer + sizeof buffer, x);
(void)error;
return std::string(buffer, end);
}
std::string quote(const std::string& text) {
std::string out = "\"";
for (char c : text) {
if (c == '"' || c == '\\') out += '\\';
out += c;
}
return out + "\"";
}
// Indents an already formatted JSON value by one level.
std::string nested(const std::string& json) {
std::string out;
for (char c : json) {
out += c;
if (c == '\n') out += " ";
}
return out;
}
std::string object(const std::vector<std::pair<std::string, std::string>>& fields) {
if (fields.empty()) return "{}";
std::string out = "{";
for (std::size_t i = 0; i < fields.size(); ++i) {
out += i == 0 ? "\n " : ",\n ";
out += quote(fields[i].first) + ": " + nested(fields[i].second);
}
return out + "\n}";
}
// Days from 1970-01-01 to a date in the proleptic Gregorian calendar.
long long daysFromCivil(long long y, unsigned m, unsigned d) {
y -= m <= 2;
const long long era = (y >= 0 ? y : y - 399) / 400;
const unsigned yoe = static_cast<unsigned>(y - era * 400);
const unsigned doy = (153 * (m > 2 ? m - 3 : m + 9) + 2) / 5 + d - 1;
const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
return era * 146097 + static_cast<long long>(doe) - 719468;
}
// Parses "YYYY-MM-DDTHH:MM:SS" followed by "Z" or "+hh:mm"/"-hh:mm" into
// milliseconds since the Unix epoch, like Date.parse.
long long parseInstant(const std::string& text) {
const int year = std::stoi(text.substr(0, 4));
const unsigned month = static_cast<unsigned>(std::stoi(text.substr(5, 2)));
const unsigned day = static_cast<unsigned>(std::stoi(text.substr(8, 2)));
const long long hour = std::stoi(text.substr(11, 2));
const long long minute = std::stoi(text.substr(14, 2));
const long long second = std::stoi(text.substr(17, 2));
const std::string zone = text.substr(19);
long long offsetMinutes = 0;
if (zone != "Z") {
const long long sign = zone[0] == '-' ? -1 : 1;
offsetMinutes = sign * (std::stoi(zone.substr(1, 2)) * 60 + std::stoi(zone.substr(4, 2)));
}
const long long seconds = daysFromCivil(year, month, day) * 86400
+ hour * 3600 + minute * 60 + second - offsetMinutes * 60;
return seconds * 1000;
}
struct ClockCheck {
bool sameInstant;
double latencySeconds;
};
ClockCheck lesson026() {
const long long a = parseInstant("2026-01-01T10:00:00Z");
const long long b = parseInstant("2026-01-01T12:00:00+02:00");
const long long received = parseInstant("2026-01-01T10:00:05Z");
const ClockCheck result{a == b, static_cast<double>(received - a) / 1000};
return result;
}
int main() {
const ClockCheck result = lesson026();
std::cout << object({
{"sameInstant", result.sameInstant ? "true" : "false"},
{"latencySeconds", num(result.latencySeconds)}
}) << "\n";
}
No browser runner for C++ yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}//! Fintech Math Bootcamp · Lesson 026 of 120
//! Timestamps, Time Zones, Calendars, and Observation Time
//! Module 03: Data, Variables, Samples, and Measurement
//!
//! Scenario: Different clock strings can describe the same instant
//! Rule: event time ≠ receipt time ≠ decision time
//!
//! Try it: Are event time and receipt time interchangeable?
//!
//! Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
//! Free course: https://courses.thefintechbuilder.com
//! Synthetic teaching example, not financial advice or a production library.
//!
//! Run it: rustc main.rs && ./main
/// Days from 1970-01-01 to a date in the proleptic Gregorian calendar.
fn days_from_civil(year: i64, month: i64, day: i64) -> i64 {
let y = if month <= 2 { year - 1 } else { year };
let era = (if y >= 0 { y } else { y - 399 }) / 400;
let yoe = y - era * 400;
let mp = if month > 2 { month - 3 } else { month + 9 };
let doy = (153 * mp + 2) / 5 + day - 1;
let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
era * 146097 + doe - 719468
}
/// Parses "YYYY-MM-DDTHH:MM:SS" followed by "Z" or "+hh:mm"/"-hh:mm" into
/// milliseconds since the Unix epoch, like Date.parse.
fn parse_instant(text: &str) -> Result<i64, String> {
let field = |from: usize, to: usize| -> Result<i64, String> {
text.get(from..to)
.and_then(|part| part.parse::<i64>().ok())
.ok_or_else(|| format!("Invalid timestamp: {}", text))
};
let (year, month, day) = (field(0, 4)?, field(5, 7)?, field(8, 10)?);
let (hour, minute, second) = (field(11, 13)?, field(14, 16)?, field(17, 19)?);
let zone = text.get(19..).unwrap_or("");
let offset_minutes = if zone == "Z" {
0
} else {
let sign = if zone.starts_with('-') { -1 } else { 1 };
sign * (field(20, 22)? * 60 + field(23, 25)?)
};
let seconds = days_from_civil(year, month, day) * 86400 + hour * 3600 + minute * 60 + second
- offset_minutes * 60;
Ok(seconds * 1000)
}
struct ClockCheck {
same_instant: bool,
latency_seconds: f64,
}
fn lesson026() -> Result<ClockCheck, String> {
let a = parse_instant("2026-01-01T10:00:00Z")?;
let b = parse_instant("2026-01-01T12:00:00+02:00")?;
let received = parse_instant("2026-01-01T10:00:05Z")?;
let result = ClockCheck {
same_instant: a == b,
latency_seconds: (received - a) as f64 / 1000.0,
};
Ok(result)
}
fn main() {
match lesson026() {
Ok(result) => println!(
"{}",
object(&[
("sameInstant", result.same_instant.to_string()),
("latencySeconds", num(result.latency_seconds)),
])
),
Err(message) => {
eprintln!("Error: {}", message);
std::process::exit(1);
}
}
}
/// Formats a number the way JSON.stringify does: shortest round-trip form, null for NaN or infinity.
fn num(x: f64) -> String {
if x.is_finite() {
format!("{}", x)
} else {
"null".to_string()
}
}
fn quote(text: &str) -> String {
format!("\"{}\"", text.replace('\\', "\\\\").replace('"', "\\\""))
}
/// Indents an already formatted JSON value by one level.
fn nested(json: &str) -> String {
json.replace('\n', "\n ")
}
fn object(fields: &[(&str, String)]) -> String {
if fields.is_empty() {
return "{}".to_string();
}
let lines: Vec<String> = fields
.iter()
.map(|(key, value)| format!(" {}: {}", quote(key), nested(value)))
.collect();
format!("{{\n{}\n}}", lines.join(",\n"))
}
No browser runner for Rust yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}/**
* Fintech Math Bootcamp · Lesson 026 of 120
* Timestamps, Time Zones, Calendars, and Observation Time
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: Different clock strings can describe the same instant
* Rule: event time ≠ receipt time ≠ decision time
*
* Try it: Are event time and receipt time interchangeable?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/timestamps-time-zones-calendars-and-observation-time/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: dotnet run (inside a console project that holds this Program.cs)
*/
using System.Globalization;
using System.Text.Json;
var jsonOptions = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
Console.WriteLine(JsonSerializer.Serialize(Lesson026(), jsonOptions));
// Milliseconds since the Unix epoch, like Date.parse.
static long ParseInstant(string text) =>
DateTimeOffset.Parse(text, CultureInfo.InvariantCulture).ToUnixTimeMilliseconds();
static ClockCheck Lesson026()
{
var a = ParseInstant("2026-01-01T10:00:00Z");
var b = ParseInstant("2026-01-01T12:00:00+02:00");
var received = ParseInstant("2026-01-01T10:00:05Z");
var result = new ClockCheck(a == b, (received - a) / 1000.0);
return result;
}
record ClockCheck(bool SameInstant, double LatencySeconds);
No browser runner for C# yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"sameInstant": true,
"latencySeconds": 5
}Prefer your own machine? Every file is in the course repository · open it in Codespaces.
Lesson notes
The rule
event time ≠ receipt time ≠ decision time