迎接2038年我们应该做什么准备?
我想我今天编写的一些软件将在 30 年后被使用。 但我也知道其中很多都是基于 UNIX 传统,将时间公开为自 1970 年以来的秒数。
#include <stdio.h>
#include <time.h>
#include <limits.h>
void print(time_t rt) {
struct tm * t = gmtime(&rt);
puts(asctime(t));
}
int main() {
print(0);
print(time(0));
print(LONG_MAX);
print(LONG_MAX+1);
}
执行结果为:
- Thu Jan 1 00:00:00 1970
- Sat Aug 30 18:37:08 2008
- Tue 1 月 19 日 03:14:07 2038
- 12 月 13 日星期五 20:45:52 1901
<块引用>函数 ctime()、gmtime() 和 localtime() 都将时间值作为参数,表示自纪元(1970 年 1 月 1 日 00:00:00 UTC,1970 年 1 月 1 日)以来的时间(以秒为单位);请参阅 time(3 ))。
我想知道作为程序员在这个领域是否有什么积极主动的事情要做,或者我们是否相信所有软件系统(又名操作系统)将来都会神奇地升级?
更新 看来 64 位系统确实是安全的:
import java.util.*;
class TimeTest {
public static void main(String[] args) {
print(0);
print(System.currentTimeMillis());
print(Long.MAX_VALUE);
print(Long.MAX_VALUE + 1);
}
static void print(long l) {
System.out.println(new Date(l));
}
}
- Wed Dec 31 16:00:00 PST 1969
- Sat Aug 30 12:02:40 PDT 2008
- Sat Aug 16 23:12:55 PST 292278994
- Sun Dec 02 08:47:04 PST 292269055
但是年份 292278994 又如何呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
到 2038 年,时间库应该全部使用 64 位整数,因此这实际上并不是什么大问题(在并非完全无人维护的软件上)。
不过,COBOL 程序可能很有趣。
By 2038, time libraries should all be using 64-bit integers, so this won't actually be that big of a deal (on software that isn't completely unmaintained).
COBOL programs might be fun though.
操作词是“应该”。
如果您需要确保面向未来,那么您可以构建自己的日期/时间类并使用它,但只有当您认为您编写的内容将在旧操作系统上使用时我才会这样做
Operative word being "should".
If you need to ensure futureproofing then you can construct your own date/time class and use that but I'd only do that if you think that what you write will be used on legacy OS'
Visual Studio 在 Visual Studio 2005 中迁移到 time_t 的 64 位表示形式(同时仍保留 _time32_t 以实现向后兼容性)。
只要您始终小心地根据 time_t 编写代码并且不要假设任何有关大小的信息,那么正如 sysrqb 指出的那样,您的编译器将解决该问题。
Visual Studio moved to a 64 bit representation of time_t in Visual Studio 2005 (whilst still leaving _time32_t for backwards compatibility).
As long as you are careful to always write code in terms of time_t and don't assume anything about the size then as sysrqb points out the problem will be solved by your compiler.
我已经编写了 time.h 的可移植替代品(目前只有 localtime()、gmtime()、mktime() 和 timegm()),即使在 32 位机器上也使用 64 位时间。 它旨在作为 time.h 的替代品放入 C 项目中。 它正在 Perl 中使用,我也打算用它修复 Ruby 和 Python 的 2038 问题。 这为您提供了 +/- 2.92 亿年的安全范围。
您可以在 y2038 项目找到代码。 请随时将任何问题发布到问题跟踪器。
至于“这在接下来的 29 年里都不会成为问题”,请仔细阅读关于该问题的演示,什么不是解决方案,以及什么是。
哦,不要忘记,许多时间系统不处理 1970 年之前的日期。事情发生在 1970 年之前,有时您需要知道时间。
I have written portable replacement for time.h (currently just localtime(), gmtime(), mktime() and timegm()) which uses 64 bit time even on 32 bit machines. It is intended to be dropped into C projects as a replacement for time.h. It is being used in Perl and I intend to fix Ruby and Python's 2038 problems with it as well. This gives you a safe range of +/- 292 million years.
You can find the code at the y2038 project. Please feel free to post any questions to the issue tracker.
As to the "this isn't going to be a problem for another 29 years", peruse this list of standard answers to that. In short, stuff happens in the future and sometimes you need to know when. I also have a presentation on the problem, what is not a solution, and what is.
Oh, and don't forget that many time systems don't handle dates before 1970. Stuff happened before 1970, sometimes you need to know when.
您始终可以实施 RFC 2550 并永远安全;-)
You can always implement RFC 2550 and be safe forever ;-)
请注意,我在 32 位 MCU 上遇到了您的帖子,并使用我的编译器运行了您的代码,这也产生了 1970 的溢出,并错误地认为我需要像 y2038 项目中的库一样的库。
然而,应该这样做来验证(注意 time_t 转换):
在我的例子中,time_t 实际上被定义为 __int_least64_t => uint64_t,并且本机 gmtime 函数采用 64 位作为输入,因此在 2038 年之后工作得很好。
但是,当不进行转换时,我的编译器确实打印了一条我愚蠢地错过的警告:
“long int”类型表达式中的整数溢出导致“-2147483648”[-Woverflow]
请注意,仅将大小写转换为 (uint32_t) 也足够了,但如果不进行转换,编译器会将
LONG_MAX+1
作为有符号 int 执行,从而导致溢出。 只有之后编译器才会将-1结果转换为调用函数的time_t,这仍然是错误的。 令人困惑的是,这似乎表明 gmtime 不是 64 位,但这是一个错误的结论长话短说:我的 libc 时间函数已经是 64 位(即使在 32 位 MCU 上),但你的帖子失败了,思考我需要额外的库(这是不需要的)。 (基本上相当于 y2038 代码已经在那里了)
Note that I ran into your post on a 32bit MCU, and ran your code with my compiler, which also produced the overflow to 1970, and mistakenly assumed I needed the library like the one from the y2038 project.
One should however do this to verify (note the time_t cast):
In my case, time_t is actually defined as a __int_least64_t => uint64_t, and the native gmtime function takes 64bit as input, so works just fine after 2038.
However, when not casting, my compiler did print a warning which I stupidly missed:
integer overflow in expression of type 'long int' results in '-2147483648' [-Woverflow]
Note that just casing to (uint32_t) was also enough, but without casting, the compiler executed
LONG_MAX+1
as a signed int, causing an overflow. Only afterwards the compiler then casts the -1 result to the time_t of the calling function, which is still wrong. That confusingly seems to indicate that the gmtime is not 64bit, but that's a wrong conclusionLong story short: My libc time functions were already 64bit (even on a 32bit MCU), but your post threw off, thinking I needed additional libraries (which were not needed). (Basically an equivalent of the y2038 code was already in there)
保留良好的文档,并包含对时间依赖性的描述。 我认为很多人都没有想过这种转变有多困难,例如 HTTP cookie 将在该日期失效。
Keep good documentation, and include a description of your time dependencies. I don't think many people have thought about how hard this transition might be, for example HTTP cookies are going to break on that date.
躲起来,因为世界末日即将来临。
但说真的,我希望编译器(或者准确地说是编写它们的人)能够处理这个问题。 他们已经快30年了。 我希望时间足够。
我们从什么时候开始为万年做准备? 是否有任何硬件制造商/研究实验室研究过最简单的方法来转向我们因此而必须拥有的任何新技术?
Hide, because the apocalypse is coming.
But seriously, I hope that compilers (or the people who write them, to be precise) can handle this. They've got almost 30 years. I hope that's enough time.
At what point do we start preparing for Y10K? Have any hardware manufacturers / research labs looked into the easiest way to move to whatever new technology we'll have to have because of it?
我认为我们应该保留这个 bug。然后到 2036 年左右我们就可以开始以大笔资金出售咨询服务来测试一切。 毕竟,这并不是我们成功管理 1999-2000 年过渡的方式。
我只是在开玩笑!
1999 年,我坐在伦敦的一家银行,当我看到一位顾问开始 Y2K 测试咖啡机时,我感到非常惊讶。 我认为,如果我们从这次惨败中学到了什么的话,那就是绝大多数软件都能正常工作,其余大部分软件如果失败也不会导致崩溃,并且可以在需要时在事件发生后修复。 因此,除非您正在处理一个非常关键的软件,否则我不会在临近时间之前采取任何特殊的预防措施。
I think that we should leave the bug in. Then about 2036 we can start selling consultancy for large sums of money to test everything. After all isn't that how we successfully managed the 1999-2000 rollover.
I'm only joking!
I was sat in a bank in London in 1999 and was quite amazed when I saw a consultant start Y2K testing the coffee machine. I think if we learnt anything from that fiasco, it was that the vast majority of software will just work and most of the rest won't cause a melt down if it fails and can be fixed after the event if needed. As such, I wouldn't take any special precautions until much nearer the time, unless you are dealing with a very critical piece of software.
我从事嵌入式工作,我想我应该在这里发布我们的解决方案。 我们的系统是32位的,我们现在卖的有30年的保修期,这意味着他们会遇到2038年的bug。 以后升级也不是解决办法。
为了解决这个问题,我们将内核日期设置为比当前日期早 28 年。 这不是随机偏移,28 年正是一周中的日期再次匹配所需的时间。 例如,我在星期四写这篇文章,而下一次 3 月 7 日是星期四是 28 年后的事了。
此外,所有与我们系统上的日期交互的应用程序都会将系统日期 (time_t) 转换为自定义 time64_t,并将 28 年偏移量应用到正确的日期。
我们制作了一个自定义库来处理这个问题。 我们使用的代码基于此:https://github.com/android/platform_bionic
因此,通过此解决方案,您可以轻松为自己赢得额外的 28 年寿命。
I work in embedded and I thought I would post our solution here. Our systems are on 32 bits, and what we sell right now has a warantee of 30 years which means that they will encounter the year 2038 bug. Upgrading in the future was not a solution.
To fix this, we set the kernel date 28 years earlier that the current date. It's not a random offset, 28 years is excatly the time it will take for the days of the week to match again. For instance I'm writing this on a thursday and the next time march 7 will be a thursday is in 28 years.
Furthermore, all the applications that interact with dates on our systems will take the system date (time_t) convert it to a custom time64_t and apply the 28 years offset to the right date.
We made a custom library to handle this. The code we're using is based off this: https://github.com/android/platform_bionic
Thus, with this solution you can buy yourself an extra 28 years easily.
考虑到我的年龄,我认为我应该支付很多养老金并支付我所有部门的费用,所以其他人将不得不安装该软件!
抱歉,如果你考虑一下你今天编写的任何软件的“净现值”,它对 2038 年软件的功能没有影响。对于任何软件项目来说,超过几年的“投资回报”都是罕见的,所以通过更快地交付软件,您可以为雇主赚更多的钱,而不是想得太远。
唯一常见的例外是必须预测未来的软件,2038 年对于抵押贷款报价系统来说已经是一个问题。
Given my age, I think I should pay a lot into my pension and pay of all my depts, so someone else will have to fit the software!
Sorry, if you think about the “net present value” of any software you write today, it has no effect what the software does in 2038. A “return on investment” of more than a few years is uncommon for any software project, so you make a lot more money for your employer by getting the software shipped quicker, rather than thinking that far ahead.
The only common exception is software that has to predict future, 2038 is already a problem for mortgage quotation systems.