数据库存储时间的时区问题

先说一下mysql中DATETIME和TIMESTAMP的区别mysql

TIMESTAMP是标准的unix timestamp,它存储的是1970-1-1到如今通过的秒数,4字节存储。mysql用这个类型还蛮方便的,一个是有不少内置的函数和trigger来处理它,好比CURRENT_TIMESTAMP宏,最关键的是在取数据的时候mysql会自动帮你处理DST和时区的问题。sql

DATETIME的范围更大,好像能够从0000-00-00 00:00:00到9999-12-31 23:59:59,8字节存储,固然mysql内部确定也是用整数而不是字符串的(说了是8字节了),因此效率不是大问题。但DATETIME不带时区,好比我在程序里生成了一个2015-05-07 15:26:00的时间(其实是+8时区的,但这个对象多是timezone naive)的,存到mysql里,再从不一样时区的地方拿出来,这个时间可能就混了。数据库

但TIMESTAMP也有两个很大的问题:服务器

  1. 4字节长度限制,它只能到2038年
  2. 不少时候咱们但愿根据用户所在地的时区显示时间而不是光显示一个服务器时间

因此比较好的作法是,数据库中使用DATETIME,而后存时间的时候一概用程序生成UTC时间(而不是local时区的时间)存进去,取出来的时候无论想显示服务器时间仍是显示用户的时间均可以处理。session

顺便提一句,根据用户所在地时区显示时间有两种作法:框架

  1. 当用户第一次访问网站的时候,用js获取时区发送到服务器上存到session里
  2. 用js处理时间的显示(我以为这种比较方便一点,毕竟不用改服务端代码)

使用这种作法的惟一缺点是sqlite3没有internal的DATETIME类型,因此在ORM框架如sqlalchemy中,它会直接存字符串进去。(sqlite3的文档也说,你要么存成int要么real要么字符串)。尽管这可能带来一些不方便和性能的降低,但我认为仍是符合“keep it simple and stupid”的原则。函数

至于用INT存时间,是另外一种可行的方法,参见http://www.liaoxuefeng.com/article/0014132675721847f569c3514034f099477...
我我的不是很喜欢这么作,由于这样你必须把模型中表示时间的成员声明为int类型。这样是比较不符合逻辑的(那些Date呀Datetime之类的类就没有用了呀,最多就有个Dateutil就行了),并且会使得程序不易读(卧槽这个publishedDate为何是int,它到底表示的是时间吗?)。总之见仁见智。性能

相关文章
相关标签/搜索