Shell Tips: Unix 时间到字面

我的工作需要天天跟报表数据打交道,在交换的文件中,一般时间的字段内容都是 Unix 时间。为了检查数据的正确性,不可避免地需要转换 Unix 时间到人类可读的字面时间。

下面想分享的是一个在 Shell 下转换 Unix 时间到字面的小方法。与前面几篇一样,这个小 shell 函数仍然可以放在 ~/.bashrc 中方便快捷使用。

# 转换 Unix 时间到本地时间字符串
function ctime()
{   
    date -d "UTC 1970-01-01 $1 secs"
}

使用方法很简单:

$ ctime 1234567890
Sat Feb 14 07:31:30 CST 2009

对 date 命令熟悉的同学会说,date 不是已经有直接转 Unix 时间的参数了吗?

$ date -d @1234567890
Sat Feb 14 07:31:30     2009

但是不好意思的是,小弟有时候用的 date 程序好老,不支持 @ 符号。

$ date --version
date (coreutils) 5.2.1
Written by David MacKenzie.

Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

PS: 写完这篇博文,我又想到了一个有趣的事情,既然很多 Linux 64 位版本的 time_t 已经是 long long 格式了,那么 date 命令有没有 year 2038 问题呢?

下面是 date (coreutils) 5.2.1 在 64 位服务器上的尝试结果:

$ date +%s -d "Tue Jan 19 11:14:07 CST 2038"
2147483647
$ date +%s -d "Tue Jan 19 11:14:08 CST 2038"
2147483648
$ date +%s -d "Tue Jan 19 11:14:09 CST 2999"
32473710849
$ ctime 2147483647
Tue Jan 19 11:14:07 CST 2038
$ ctime 2147483648
Sat Dec 14 04:51:44 LMT 1901
$ ctime 32473710849
Mon Mar 28 07:33:53 LMT 1910

看来字面时间和 Unix 时间之间互转存在着问题啊!但是用 Ubuntu 11.04 的 date (GNU coreutils) 8.5 尝试就不存在这个问题了。

EE vs. CS

这是一篇很古老的文章,翻译得不好,大家将就着看。

固定链接:http://share.solrex.org/os/ee_vs_cs_cn.html

从前,在一个离这儿不远的国家,一个国王召来他的两个谋臣进行一项测试。国王给他们看了一个闪闪发光的金属盒,盒子上面有两个插槽,一个控制按钮和一个手柄,然后问道:“你们认为这是个什么东西?”

其中一个谋臣,电子工程师,抢先答道:“陛下,这是一个烤吐司机。”国王问他:“如果让你给它设计一个嵌入式计算机,你会怎么做?”这个工程师回答说:“利用一个4位的微控制器即可,我将写一个简单的程序读入亮度盘(译注:the darkness knob,不知道是什么东西),将其量化到从雪白到煤黑的 16 阶亮度水平上。这个程序将使用该亮度水平作为 16 个初始时间值表的索引,然后启动加热元件,用该亮度水平映射到的时间初始化计时器。在计时结束后,关掉加热元件,弹出烤好的吐司。如果您愿意的话,下星期我就能给您一个可以工作的原型。”

第二个谋臣,计算机科学家,立刻认识到了这种短视想法的危险。他说:“烤吐司机并不仅仅是用来把面包变成吐司的,它们同样会被用来加热冷冻华夫饼。在您面前所放置的其实是一个早餐厨具,当您的臣民变得越来越老练时,他们将需要它提供更多功能。他们会希望早餐厨具同样可以用来烤香肠、煎培根和炒鸡蛋,一个只能做吐司的烤吐司机将会很快被大众废弃。如果我们不未雨绸缪,在不远的几年后我们就不得不完全重新设计烤吐司机。”

“考虑到这一点,我们可以制定一个更好的解决方案。首先,创建一个早餐食品基类,特殊化这个基类到几个派生类:谷物、猪肉和禽肉。特殊化的过程可以重复进行下去,比如谷物可以派生出吐司、松饼、薄煎饼和华夫饼;猪肉可以派生出香肠、links和培根;禽肉可以派生出炒鸡蛋、煮鸡蛋、荷包蛋、煎鸡蛋和多种煎蛋卷类。”

“火腿奶酪煎蛋卷类尤其值得特别注意,它必须同时继承猪肉、奶制品和禽肉类的特点,除了使用多重继承,这个问题无法得到妥善解决。在运行时,该程序必须创建合适的对象,并发送消息到该对象:‘把自己弄熟。’当然,由于多态性,这条消息的语义取决于该对象的类型,所以它对于吐司对象和炒鸡蛋对象分别具有不同的含义。”

“回首目前我们的进程,可以看到,分析阶段揭露了一个基本的需求,那就是该厨具需要能做出任何种类的早餐。在设计阶段,我们发现了一些衍生的需求,特别是我们需要一个面向对象的、支持多重继承的语言。当然,没有哪个用户希望当煎培根时鸡蛋变凉了,所以并行处理能力也是必要的。”

“我们绝对不能忘记用户界面。用来控制食物的手柄缺乏通用性,亮度盘令人困惑。一个产品必须具有友好的图形界面,否则不会受到市场欢迎。当这个早餐厨具启动时,用户应该看到一个牛仔出现在屏幕上。用户点击它后,一条消息“正在启动 UNIX v.8.3”将显示在屏幕上。(当该产品推出时,Unix 8.3 应该已经发布了。)然后用户可以下拉菜单,点击他们想做的食品。”

“当在设计阶段做出首先规划软件的聪明决策之后,在实施阶段剩下的只是选择一个合适的硬件平台了。一个使用 Intel 80386 CPU,拥有 8 兆内存、30 兆硬盘和 VGA 显示器的机器应该足够了[1]。如果你选择了一个多任务、面向对象、支持多重继承且内建图形用户界面库的编程语言,写这样一个程序是件轻易而举的事情。想想如果我们傻乎乎地允许一个硬件优先、将我们锁定在一个 4 位微控制器上的愚蠢设计将会给我们带来多少困难!”

国王听完他这番话,作出了将这个计算机科学家斩首的英明决定。人们从此过上了幸福快乐的生活。

[1] 在这篇文章出现的当时,这应该算是挺先进的配置了。

APUE, A Great Book

这两周是选课试听期,还没有正式开始上课,所以有点空闲就翻了翻 UINX 环境高级编程(Advanced Programming in the UNIX Environment, 2e),看了七八章,发现这本书真的是无愧于“UNIX 编程圣经”的称号。书中对编程中可能遇到的问题讲解得非常系统和详细,尤其当看到自己以前遇到过问题的地方时,简直就有一种顿悟的感觉,就想感叹一句“哦,原来如此!”。

我平常在写程序时,遇到问题总是求助于 Google。对那些讲编程技巧的书向来不怎么感冒(尤其是中国人写的),总觉得那种书根本不适合花时间仔细看一遍。这种问题驱动式的学习方式固然在解决某一特定问题时显得快捷高效,但是也往往受限于一叶障目不见泰山的困境。在解决了某一问题之后,对其它同类问题没有足够关注,导致再遇到类似问题时仍需要去搜索答案。

问题驱动式的学习方式会导致对问题的了解不够系统和深入,但如果仅仅拿本大部头慢慢翻完的话,又会枯燥无味,而且体会也不深。我觉得读编程书的最好方法就是,先有一定量的实践,再去看书,而且要保持对书中习题和代码的练习量。有时候不妨先看实例代码再看正文解释,如果代码看得懂,看作者的解释是否和自己理解一样;如果代码看不懂,就会加深对正文的注意度。而且有时候读那些入门级的教科书,不妨只看代码。

当然,在编程的时候,桌子上应该有几本经典图书当作手册来参考,不时地重读一下某些章节会很有好处。像 APUE,我就觉得非常适合作为案头书,做 Linux/Unix 开发的程序员买一本看看绝对不会失望。