14

假设美国加利福尼亚州的用户选择了日期、时间和时区:

全球啤酒马拉松将于 2013 年 8 月15 日上午 10:00,UTC-08:00开始

中欧的另一位用户打开显示此日期和时间的页面。他不想计算时间(啤酒已经很少了)。他只想看到这个日期和时间:

2013 年 8 月 15 日 19:00

鉴于浏览器接收到加利福尼亚州用户输入的日期和时间信息:

有没有办法在没有外部网络服务的情况下在 javascript中进行正确的转换?也就是说,要检测到 UTC-08:00 上午 10 点实际上应该是 UTC-07:00 上午 10 点,因为它是夏令时。

也许我一开始就理解错了,但我不想让进入的用户思考他应该选择UTC-08:00(PST)还是UTC-07:00(PDT)。我假设由于 CA 的标准时区是 PST,因此人们不会在夏季转向思考 PDT。还是他们?!

在中欧,标准日期为 UTC+01:00,夏令时日期为 UTC+02:00。因此,CA 和欧洲之间的差异应该是 9 小时,一年中的两个时段除外,当一个或另一个区域在标准和夏令时模式之间切换时。

更新:

经过更多思考和阅读评论后,我最理想的需要是:

var utcOffset = f('2013-08-15T10:00', 'America/Los_Angeles');
// utcOffset == "-07:00"
var utcOffset = f('2013-11-15T10:00', 'America/Los_Angeles');
// utcOffset == "-08:00"

到目前为止,Guido Preite 建议的moment.js/timezone 插件似乎能够做到这一点(或多或少)。

任何其他方式,使用浏览器API?

4

3 回答 3

23

有没有办法在没有外部网络服务的情况下在 javascript 中进行正确的转换?也就是说,要检测到 UTC-08:00 上午 10 点实际上应该是 UTC-07:00 上午 10 点,因为它是夏令时。

10:00-8 和 10:00-7 是两个不同的时间点。它们分别等于 18:00Z 和 17:00Z (Z = UTC)。当您根据偏移量进行测量时,夏令时不会进入图片。曾经。

我假设由于 CA 的标准时区是 PST,因此人们不会在夏季转向思考 PDT。还是他们?!

一般来说,人们只会想到“太平洋时间”,即冬天的 PST 和夏天的 PDT。但计算机更精确。当您看到 PST 时,它表示 UTC-8。当您看到 PDT 时,它表示 UTC-7。使用一种形式标记同时引用另一种形式的偏移量是无效的。

时区缩写可能不明确。理想情况下,以编程方式引用区域时,您应该使用 IANA 区域名称,例如America/Los_Angeles. 但是,目前这在所有没有库的 JavaScript 运行时中是不可能的。(他们正在努力解决这个问题。)

在中欧,标准日期为 UTC+01:00,夏令时日期为 UTC+02:00。因此,CA 和欧洲之间的差异应该是 9 小时,一年中的两个时段除外,当一个或另一个区域在标准和夏令时模式之间切换时。

正确的。它们可能相隔 8、9 或 10 小时。不过,它们在完全不同的时间切换,所以不要试图自己管理。

到目前为止,Guido Preite 建议的 moment.js/timezone 插件似乎能够做到这一点(或多或少)。

Moment-timezone是一个很棒的库。但是,从您描述的情况来看,我认为您不需要像您想的那样担心时区转换。看看你能不能遵循这个逻辑:

  1. 加利福尼亚的用户在文本框中输入日期和时间。
  2. 您将该文本框值读入字符串,并将其解析为日期:

    var dt = new Date("8/15/2013 10:00");
    

    或使用 moment.js:

    var m = moment("8/15/2013 10:00", "M/D/YYYY HH:mm");
    
  3. 因为这是在用户的计算机上完成的,所以 JavaScript 会自动假定这是一个本地日期和时间。您无需提供任何偏移量或时区信息。

  4. 这确实意味着由于 DST 转换,输入的时间可能无效或不明确。事实上,JavaScript 在处理这个问题方面做得并不好——你会在不同的浏览器上得到不同的结果。如果您想明确,那么您将提供一个偏移量。

    // PST
    var dt = new Date("3/11/2013 1:00 UTC-08:00");
    
    // PDT
    var dt = new Date("3/11/2013 1:00 UTC-07:00");
    
  5. 一旦你有了 a Date(或 a moment),你就可以评估它的 UTC 等价物:

    var s = dt.toISOString();  //  2013-08-15T17:00:00Z
    

    与 moment.js 相同,但您将获得更好的浏览器支持:

    var s = m.toISOString();  //  2013-08-15T17:00:00Z
    
  6. 您将该 UTC 值存储在数据库中。

  7. 中欧的另一个用户过来加载数据。

  8. 您将其输入到JavaScriptDatemomentJavaScript 中:

    var dt = new Date("2013-08-15T17:00:00Z");
    

    或使用 moment.js(同样,更好的浏览器支持)

    var m = moment("2013-08-15T17:00:00Z")
    
  9. 因为 JavaScript 知道本地计算机的时区规则,所以您现在可以显示此日期,它将与中欧时区一起显示:

    var s = dt.ToString();  //  browser specific output
    // ex: "Thu Aug 15 2013 19:00:00 GMT+0200 (Central Europe Daylight Time)"
    

    或者使用moment.js,可以更好的控制输出格式

    var s = m.format("DD/MM/YYYY HH:mm"); // "15/08/2013 19:00"
    

    你也可以让 moment.js 决定应该输出什么本地化格式:

    var s = m.format("llll"); // "Thu, 15 Aug 2013 19:00"
    

总而言之 - 如果您只对在本地时区(无论可能是什么时区)进行转换感兴趣,那么您只需Date. Moment.js 将使解析和格式化变得更容易,但这不是绝对必需的。

只有少数场景需要时区库(例如 moment-timezone 或其他)。

  • 您想要转换到或从不是本地时区或 UTC 的区域。

  • 您正在使用过去的日期,并且从那时起时区规则或夏令时规则发生了变化,并且您的日期在新规则下的解释与旧规则不同。这有点技术性,但确实会发生。在此处此处阅读更多信息。

于 2013-08-02T16:17:54.647 回答
1

默认构造函数创建本地时间的实例

var localDate = new Date(); 

我现在无法测试它,但您应该能够提供您的日期时间(作为构造函数的参数)..

var eventDate = [SOMEDATE];
var localDate = new Date(eventDate);

..然后你应该能够调用像getMonth这样的日期对象函数,它返回本地时区的数据。写在:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

注1:没有服务器=根本没有服务器|数据库?如果有,日期应在 db 中保存为 UTC 并将其加载为每个用户的本地时间。这样您就不必担心转换。

注意2:这个问题有一些代码显示如何获取时区差异:如何获取客户端的确切本地时间?

于 2013-08-02T10:23:51.603 回答
1

我根据其他示例开发了此解决方案...希望这对您有用!在jsfiddle上可用。

/* 
* Author: Mohammad M. AlBanna
* Website: MBanna.me
* Description: Get the current time in different time zone 
*/

//Check daylight saving time prototype
Date.prototype.stdTimezoneOffset = function() {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}

Date.prototype.dst = function() {
    return this.getTimezoneOffset() < this.stdTimezoneOffset();
}

var today = new Date();
var isDST = today.dst() ? true : false;
var pstOffset = isDST ? 7 : 8;
var cstOffset = isDST ? 5 : 6;
var estOffset = isDST ? 4 : 5;
var gmtOffset = 1;

pstOffset = pstOffset * 60 * 60 * 1000;
cstOffset = cstOffset * 60 * 60 * 1000;
estOffset = estOffset * 60 * 60 * 1000;
gmtOffset = gmtOffset * 60 * 60 * 1000;

var todayMillis = today.getTime();
var timeZoneOffset = (today.getTimezoneOffset() * 60 * 1000);

var curretPST = todayMillis - pstOffset; 
var curretCST = todayMillis - cstOffset; 
var curretEST = todayMillis - estOffset;
var curretGMT = todayMillis - gmtOffset;

addP("PST Time : " + new Date(curretPST).toUTCString());
addP("CST Time : " + new Date(curretCST).toUTCString());
addP("EST Time : " + new Date(curretEST).toUTCString());
addP("GMT Time : " + new Date(curretGMT).toUTCString());
addP("Local Time : " + new Date(today.getTime() - timeZoneOffset ).toUTCString());

function addP(value){
    var p = document.createElement("p");
    p.innerHTML = value;
    document.body.appendChild(p);
}
于 2017-09-22T01:24:02.747 回答