在JavaScript中将日期转换为另一个时区

Convert date to another timezone in JavaScript

我正在寻找一个功能,将日期在一个时区转换为另一个时区。

它需要两个参数,

  • 日期(格式为"2012/04/10 10:10:30 +0000")
  • 时区字符串("亚洲/雅加达")

时区字符串在http://en.wikipedia.org/wiki/Zone.tab中描述

是否有捷径可寻?


对于moment.js用户,您现在可以使用moment-timezone。使用它,你的功能看起来像这样:

1
2
3
4
function toTimeZone(time, zone) {
    var format = 'YYYY/MM/DD HH:mm:ss ZZ';
    return moment(time, format).tz(zone).format(format);
}


除Safari之外的大多数桌面(非移动)浏览器都支持带参数的toLocaleString函数,旧浏览器通常会忽略这些参数。

1
new Date().toLocaleString('en-US', { timeZone: 'Asia/Jakarta' })


无耻地偷走了:http://www.techrepublic.com/article/convert-the-local-time-to-another-time-zone-with-this-javascript/6016329

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * function to calculate local time
 * in a different city
 * given the city's UTC offset
 */

function calcTime(city, offset) {

    // create Date object for current location
    var d = new Date();

    // convert to msec
    // add local time zone offset
    // get UTC time in msec
    var utc = d.getTime() + (d.getTimezoneOffset() * 60000);

    // create new Date object for different city
    // using supplied offset
    var nd = new Date(utc + (3600000*offset));

    // return time as a string
    return"The local time in" + city +" is" + nd.toLocaleString();
}

此功能通过提供城市/国家/地区的名称和偏移值来计算时区值


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var aestTime = new Date().toLocaleString("en-US", {timeZone:"Australia/Brisbane"});
aestTime = new Date(aestTime);
console.log('AEST time: '+aestTime.toLocaleString())

var asiaTime = new Date().toLocaleString("en-US", {timeZone:"Asia/Shanghai"});
asiaTime = new Date(asiaTime);
console.log('Asia time: '+asiaTime.toLocaleString())

var usaTime = new Date().toLocaleString("en-US", {timeZone:"America/New_York"});
usaTime = new Date(usaTime);
console.log('USA time: '+usaTime.toLocaleString())

var indiaTime = new Date().toLocaleString("en-US", {timeZone:"Asia/Kolkata"});
indiaTime = new Date(indiaTime);
console.log('India time: '+indiaTime.toLocaleString())

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString


好的,找到了!

我正在使用timezone-js。这是代码:

1
2
3
4
var dt = new timezoneJS.Date("2012/04/10 10:10:30 +0000", 'Europe/London');
dt.setTimezone("Asia/Jakarta");

console.debug(dt); //return formatted date-time in asia/jakarta


得到它了 !

想要强制显示的日期=服务器日期,不要使用本地设置(UTC)。

我的服务器是GMT-6 - > new Date()。getTimezoneOffset()= 360。

1
2
3
myTZO = 360;
myNewDate=new Date(myOldDateObj.getTime() + (60000*(myOldDateObj.getTimezoneOffset()-myTZO)));
alert(myNewDate);


如果您不想导入一些大型库,您可以使用Intl.DateTimeFormat将Date对象转换为不同的时区。

1
2
3
4
5
6
7
8
9
10
11
12
// Specifying timeZone is what causes the conversion, the rest is just formatting
const options = {
  year: '2-digit', month: '2-digit', day: '2-digit',
  hour: '2-digit', minute: '2-digit', second: '2-digit',
  timeZone: 'Asia/Jakarta',
  timeZoneName: 'short'
}
const formater = new Intl.DateTimeFormat('sv-SE', options)
const startingDate = new Date("2012/04/10 10:10:30 +0000")

const dateInNewTimezone = formater.format(startingDate)
console.log(dateInNewTimezone) // 12-04-10 17:10:30 GMT+7

我们将为您解决偏差,夏令时和过去的变化。


如果你只是需要转换时区,我已经上传了一个简化版本的时间 - 时区,只有最小的功能。它的~1KB +数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
S.loadData({
   "zones": [
       "Europe/Paris|CET CEST|-10 -20|01010101010101010101010|1GNB0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0|11e6",
       "Australia/Sydney|AEDT AEST|-b0 -a0|01010101010101010101010|1GQg0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0|40e5",
    ],
   "links": [
       "Europe/Paris|Europe/Madrid",
    ]
});

let d = new Date();
console.log(S.tz(d,"Europe/Madrid").toLocaleString());
console.log(S.tz(d,"Australia/Sydney").toLocaleString());

这是我的代码,它工作得很好,你可以试试下面的演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$(document).ready(function() {
   //EST
setInterval( function() {
var estTime = new Date();
 var currentDateTimeCentralTimeZone = new Date(estTime.toLocaleString('en-US', { timeZone: 'America/Chicago' }));
var seconds = currentDateTimeCentralTimeZone.getSeconds();
var minutes = currentDateTimeCentralTimeZone.getMinutes();
var hours =  currentDateTimeCentralTimeZone.getHours()+1;//new Date().getHours();
 var am_pm = currentDateTimeCentralTimeZone.getHours() >= 12 ?"PM" :"AM";

if (hours < 10){
     hours ="0" + hours;
}

if (minutes < 10){
     minutes ="0" + minutes;
}
if (seconds < 10){
     seconds ="0" + seconds;
}
    var mid='PM';
    if(hours==0){ //At 00 hours we need to show 12 am
    hours=12;
    }
    else if(hours>12)
    {
    hours=hours%12;
    mid='AM';
    }
    var x3 = hours+':'+minutes+':'+seconds +' '+am_pm
// Add a leading zero to seconds value
$("#sec").html(x3);
},1000);


});
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</head>
<body>
<p class="date_time">
</p>
</body>
</html>


您可以使用toLocaleString()方法来设置时区。

1
new Date().toLocaleString('en-US', { timeZone: 'Indian/Christmas' })

对于印度,您可以使用"印度/圣诞节",以下是各种时区,

1
2
3
4
5
6
7
8
9
10
"Antarctica/Davis",
   "Asia/Bangkok",
   "Asia/Hovd",
   "Asia/Jakarta",
   "Asia/Phnom_Penh",
   "Asia/Pontianak",
   "Asia/Saigon",
   "Asia/Vientiane",
   "Etc/GMT-7",
   "Indian/Christmas"


设置一个带有年份,月份和日期的变量,用" -"符号分隔,再加上"T"和时间用HH:mm:ss模式,然后是字符串末尾的+01:00(在我的例子中是时区是+1)。然后使用此字符串作为日期构造函数的参数。

1
2
3
4
//desired format: 2001-02-04T08:16:32+01:00
dateAndTime = year+"-"+month+"-"+day+"T"+hour+":"+minutes+":00+01:00";

var date = new Date(dateAndTime );

我应该注意到,我可以使用哪些外部库受到限制。 moment.js和timezone-js对我来说不是一个选择。

我拥有的js日期对象是UTC。我需要在特定的时区(在我的情况下为'America / Chicago')中获取此日期的日期和时间。

1
2
3
4
5
6
7
8
9
10
11
 var currentUtcTime = new Date(); // This is in UTC

 // Converts the UTC time to a locale specific format, including adjusting for timezone.
 var currentDateTimeCentralTimeZone = new Date(currentUtcTime.toLocaleString('en-US', { timeZone: 'America/Chicago' }));

 console.log('currentUtcTime: ' + currentUtcTime.toLocaleDateString());
 console.log('currentUtcTime Hour: ' + currentUtcTime.getHours());
 console.log('currentUtcTime Minute: ' + currentUtcTime.getMinutes());
 console.log('currentDateTimeCentralTimeZone: ' +        currentDateTimeCentralTimeZone.toLocaleDateString());
 console.log('currentDateTimeCentralTimeZone Hour: ' + currentDateTimeCentralTimeZone.getHours());
 console.log('currentDateTimeCentralTimeZone Minute: ' + currentDateTimeCentralTimeZone.getMinutes());

UTC目前比"America / Chicago"早6个小时。输出是:

1
2
3
4
5
6
7
currentUtcTime: 11/25/2016
currentUtcTime Hour: 16
currentUtcTime Minute: 15

currentDateTimeCentralTimeZone: 11/25/2016
currentDateTimeCentralTimeZone Hour: 10
currentDateTimeCentralTimeZone Minute: 15


看了很多,包括这个页面的链接,我发现这篇很棒的文章,使用时刻时区:

JavaScript: Using Moment.js to Display Dates & Times in User’s Timezone

总结一下:

获取用户的时区

1
2
var tz = moment.tz.guess();
console.info('Timezone: ' + tz);

返回例如:时区:欧洲/伦敦

设置默认用户时区

1
moment.tz.setDefault(tz);

设置自定义时区

1
moment.tz.setDefault('America/Los_Angeles');

将日期/时间转换为本地时区,假设原始日期/时间为UTC

1
moment.utc('2016-12-25 07:00').tz(tz).format('ddd, Do MMMM YYYY, h:mma');

返回:2016年12月25日星期日上午7:00

将日期/时间转换为LA时间

1
moment.utc('2016-12-25 07:00').tz('America/Los_Angeles').format('ddd, Do MMMM YYYY, h:mma');

退货时间:2016年12月24日星期六,晚上11:00

从LA时间转换为伦敦

1
moment.tz('2016-12-25 07:00', 'America/Los_Angeles').tz('Europe/London').format( 'ddd, Do MMMM YYYY, h:mma' );

返回:2016年12月25日星期日下午3:00


你也可以使用
https://www.npmjs.com/package/ctoc_timezone

它有很简单的实现和格式定制。

更改toTimeZone中的格式:

CtoC.toTimeZone(new Date(),"EST","Do MMM YYYY hh:mm:ss #{EST}");

输出:

28th Feb 2013 19:00:00 EST

您可以在doc中探索多种功能。


您也可以尝试将日期时区转换为印度:

1
2
3
4
5
var indianTimeZoneVal = new Date().toLocaleString('en-US', {timeZone: 'Asia/Kolkata'});
var indainDateObj = new Date(indianTimeZoneVal);
indainDateObj.setHours(indainDateObj.getHours() + 5);
indainDateObj.setMinutes(indainDateObj.getMinutes() + 30);
console.log(indainDateObj);


你可以使用一个名为'timezones.json'的npm模块;它基本上由一个json文件组成,其中的对象包含有关夏令时和偏移的信息,....

对于asia / jakarta,它将能够返回此对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
 "value":"SE Asia Standard Time",
 "abbr":"SAST",
 "offset": 7,
 "isdst": false,
 "text":"(UTC+07:00) Bangkok, Hanoi, Jakarta",
 "utc": [
   "Antarctica/Davis",
   "Asia/Bangkok",
   "Asia/Hovd",
   "Asia/Jakarta",
   "Asia/Phnom_Penh",
   "Asia/Pontianak",
   "Asia/Saigon",
   "Asia/Vientiane",
   "Etc/GMT-7",
   "Indian/Christmas"
  ]
}

你可以在这里找到它:

https://github.com/dmfilipenko/timezones.json

https://www.npmjs.com/package/timezones.json

希望它有用


我在使用Moment Timezone时遇到了麻烦。我正在添加这个答案,如果其他人面临同样的问题。所以我的API来自日期字符串2018-06-14 13:51:00。我知道这存储在UTC中,但字符串不能说明问题。

我让时间时区知道,这个日期的时区来自:

1
2
3
let uTCDatetime = momentTz.tz("2018-06-14 13:51:00","UTC").format();
// If your datetime is from any other timezone then add that instead of"UTC"
// this actually makes the date as : 2018-06-14T13:51:00Z

现在我想通过执行以下操作将其转换为特定时区:

1
2
let dateInMyTimeZone = momentTz.tz(uTCDatetime,"Asia/Kolkata").format("YYYY-MM-DD HH:mm:ss");
// now this results into: 2018-06-14 19:21:00, which is the corresponding date in my timezone.

熟悉java 8 java.time软件包或joda-time的人可能会喜欢这个块上的新孩子:js-joda库。

安装

1
npm install js-joda js-joda-timezone --save

1
2
3
4
5
6
7
8
9
10
11
<script src="node_modules/js-joda/dist/js-joda.js">
<script src="node_modules/js-joda-timezone/dist/js-joda-timezone.js">

var dateStr = '2012/04/10 10:10:30 +0000';
JSJoda.use(JSJodaTimezone);
var j = JSJoda;
// https://js-joda.github.io/js-joda/esdoc/class/src/format/DateTimeFormatter.js~DateTimeFormatter.html#static-method-of-pattern
var zonedDateTime = j.ZonedDateTime.parse(dateStr, j.DateTimeFormatter.ofPattern('yyyy/MM/dd HH:mm:ss xx'));
var adjustedZonedDateTime = zonedDateTime.withZoneSameInstant(j.ZoneId.of('America/New_York'));
console.log(zonedDateTime.toString(), '=>', adjustedZonedDateTime.toString());
// 2012-04-10T10:10:30Z => 2012-04-10T06:10:30-04:00[America/New_York]

在真正的Java性质,它是非常冗长的大声笑。但是,作为一个移植的java库,特别是考虑到他们移植了1800个测试用例,它也可能非常准确地工作。

计时操作很难。这就是为什么许多其他库在边缘情况下都有问题。 Moment.js似乎正确的时区,但我见过的其他js libs,包括timezone-js,似乎不值得信赖。


您当前时区的时区偏移量

1
date +%s -d '1 Jan 1970'

对于我的GMT + 10时区(澳大利亚),它返回-36000


我最近在打字稿中做了这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// fromTimezone example : Europe/Paris, toTimezone example: Europe/London
private calcTime( fromTimezone: string, toTimezone: string, dateFromTimezone: Date ): Date {
  const dateToGetOffset = new Date( 2018, 5, 1, 12 );

  const fromTimeString = dateToGetOffset.toLocaleTimeString("en-UK", { timeZone: fromTimezone, hour12: false } );
  const toTimeString = dateToGetOffset.toLocaleTimeString("en-UK", { timeZone: toTimezone, hour12: false } );

  const fromTimeHours: number = parseInt( fromTimeString.substr( 0, 2 ), 10 );
  const toTimeHours: number = parseInt( toTimeString.substr( 0, 2 ), 10 );

  const offset: number = fromTimeHours - toTimeHours;

  // convert to msec
  // add local time zone offset
  // get UTC time in msec
  const dateFromTimezoneUTC = Date.UTC( dateFromTimezone.getUTCFullYear(),
    dateFromTimezone.getUTCMonth(),
    dateFromTimezone.getUTCDate(),
    dateFromTimezone.getUTCHours(),
    dateFromTimezone.getUTCMinutes(),
    dateFromTimezone.getUTCSeconds(),
  );

  // create new Date object for different city
  // using supplied offset
  const dateUTC = new Date( dateFromTimezoneUTC + ( 3600000 * offset ) );

  // return time as a string
  return dateUTC;
}

我使用"en-UK"格式,因为它很简单。可能是"en-US"或其他任何有效的东西。

如果第一个参数是您的区域设置时区并且seconde是您的目标时区,则它返回具有正确偏移量的Date对象。


快速和脏的手动小时更换器和返回:

1
return new Date(new Date().setHours(new Date().getHours()+3)).getHours()

我不知道将日期对象转换为任何时区的简单方法,但如果要将其转换为本地时区,则可以将其与Date.prototype.getTime()转换为相应的毫秒数,然后再返回。

1
2
date = new Date('2016-05-24T13:07:20');
date = new Date(date.getTime());

例如,如果你像我一样在奥地利(而且是夏天),date.getHours()现在将返回15而不是13

我已经读过各种日期时间函数在某些浏览器中可能会出现非标准行为,因此请先测试一下。我可以确认它在Chrome中有效。