背景:我正在用Angular JS作为web界面和Rails API构建一个应用程序。我遇到的问题是从Angular传递到Rails的日期。
Issue:我有一个带有Date of Birth日期字段的表单,当用户输入他的出生日期说1985年3月1日时,Angular将其解释为1985-03-01 00:00 +0800(如果你在香港或新加坡)并向Rails发送请求。Rails对它做的第一件事是将其转换为UTC,这意味着日期时间现在是1985-02-28 16:00 UTC。因此,当日期保存到数据库日期列时,它变成Feb 28, 1985。
现在的解决方案:我现在所做的是在Angular方面,我得到时区偏移时间并将其添加到日期,所以不是1985-03-01 00:00 +0800,而是现在1985-03-01 08:00 +0800。当Rails获得它时,它将转换为1985-03-01 00:00 UTC,从而将正确的日期保存到db。然而,我相信这是解决这个问题的一个更好的选择。
考虑在Rails中解析日期,然而我看到的参数[:dob]在我得到它的时候已经是UTC了。我很想知道是否有比我目前的解决方案更好的做法。感谢您的任何评论和反馈。
这个问题实际上很常见,它源于两个独立但相关的问题:
-
JavaScript
Date
对象命名错误。它实际上是一个日期+时间对象 -
JavaScript
Date
对象始终具有其运行环境的时区特征。
对于只有日期的值,比如date-of-birth,这个问题的最佳解决方案是不向服务器发送完整的时间戳。只发送日期部分。
-
首先,在时间上增加12小时,用正午代替午夜。这是为了避免巴西等时区的夏令时问题,在巴西,夏令时发生在午夜。(否则,您可能会遇到DOB提前一天出来的边缘情况。)
-
然后以ISO格式(YYYY-MM-DD)的字符串形式输出该值的日期部分。
的例子:
var dt = // whatever Date object you get from the control
dt.setHours(dt.getHours() + 12); // adjust to noon
var pad = function(n) { return (n < 10 ? '0' : '') + n; }
var dob = dt.getFullYear() + '-' + pad(dt.getMonth()+1) + '-' + pad(dt.getDate());
另一种常见的方法是:
var dt = // whatever Date object you get from the control
dt.setHours(dt.getHours() + 12); // adjust to noon
dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset()); // adjust for the time zone
var dob = dt.toISOString().substring(0,10); // just get the date portion
在Rails方面,使用Date
对象而不是DateTime
。与JavaScript不同,Rails的Date
对象是一个只有日期的对象——这对于出生日期来说是完美的。