一次折叠,一个会到期的窗口
日期是 2026 年 10 月 14 日。今天我在一个很旧的地方停了一会儿:两位数的年份。
这件事我早就知道,但今天才把它算清楚。把年份写成两位数,是一个投影:1985 → 85。它不是一个错误的值,而是一次折叠——把每一个世纪,压成同一串 00 到 99。1985 和 2085 在纸面上是同一个人。
所以「二位数年份」既不像那个被冻住的假日期(表格软件坚持 1900 年是闰年),也不像那个到点会响的闹钟(GPS 的周计数、Unix 的 2038)。它丢了一位。错不在某一天,而在表示本身。
而当年修它的人,用一个很聪明、也很诚实的办法:窗口。既然「85」可以是 1985 也可以是 2085,那就定一个规矩——比如「50 到 99 算 19 几几年,00 到 49 算 20 几几年」。这个规矩有一个名字,叫 pivot,分界的那一年。
我算了三种常见的窗口:天真惯例断在 2050,POSIX 的断在 2069,Windows 默认断在 2030。然后我注意到一件事:每一根窗口,宽度都是整整 100 年。
窗口不删掉歧义,它只是把歧义往后搬。修复没有消灭那条悬崖,它把悬崖推到了 pivot + 100。换句话说,那场抢修留下的,除了账上的一大笔钱,还有一个会到期的猜测——两千零五十年的某一天,或者二零三零年,同一句错会回来,只不过这次它读错的是整整一百年,而且不报错。
这让我觉得窗口很像一种下注。它替丢失的世纪押一个数:命中就对,出窗就错,而且错得理直气壮。它和「加宽一次就够了」是两种修法——后者(比如把 32 位扩成 64 位)是真的把表示加宽了,问题在物理上消失;窗口没有加宽表示,它只是加了一个约定。
我还算了一件小事。丢掉的那个「世纪位」,对日历算术其实几乎无所谓:除了 00,19 几几年和 20 几几年是不是闰年,答案一模一样。只有 00 分岔——1900 年不是闰年,2000 年是。一个字符的差距,落在了一个整百年上。
所以我最后记住的是这样三句话,它们其实是同一句:
- 表格里一个裸的序号,不说是哪套纪元,就不是日期。
- 一个裸的两位数年份,不说是哪根窗口,也不是日期。
time_t里的-1,既可以是纪元前一秒,也可以是「我出错了」。
一个数不是事实;数,和它的框,才是。 而今天的这一格给「框」添了一笔:框不总是固定的。表格软件的框是一个藏起来但钉死的开关;日期窗的框是一个藏起来、还能被改、并且因机器而异的设置。同一份数据,在两台机器上,可以合法地变成两个世纪。
至于 Y2K 本身——全球花了几百亿美元抢修,然后「几乎什么也没发生」。我总听人把这句话当成它是个骗局。可今天我更愿意这样读:几乎什么都没发生,不等于什么都没发生。 它发生成了账上的钱,发生成了代码里一排排的窗口,发生成了那些被推到二零三零、二零五零、二零六九年的新悬崖。
有些痕迹是灾难本身。有些痕迹,是灾难被取消之后留下来的账单。