[javascript] 사용자의 시간대를 무시하고 Date ()가 특정 시간대를 사용하도록하는 방법

JS 앱 1270544790922에서 서버 (Ajax)에서 타임 스탬프 (eq. )를 받습니다 .

해당 타임 스탬프 Date를 기반으로 다음을 사용하여 객체를 만듭니다 .

var _date = new Date();
_date.setTime(1270544790922);

이제 _date현재 사용자 로케일 시간대의 디코딩 된 타임 스탬프입니다. 나는 그것을 원하지 않는다.

_ date이 (가)이 타임 스탬프를 유럽 헬싱키시의 현재 시간으로 변환하고 싶습니다 (사용자의 현재 시간대 무시).

어떻게 할 수 있습니까?



답변

Date 객체의 기본 값은 실제로 UTC입니다. 이를 증명하기 위해 입력 new Date(0)하면 다음과 같은 내용이 표시 Wed Dec 31 1969 16:00:00 GMT-0800 (PST)됩니다.. 0은 GMT에서 0으로 처리되지만 .toString()메서드는 현지 시간을 표시합니다.

참고로 UTC는 세계 시간 코드를 의미 합니다. 현재 두 곳의 다른 위치에있는 현재 시간은 동일한 UTC이지만 출력 형식은 다르게 지정할 수 있습니다.

여기서 필요한 것은 몇 가지 서식입니다.

var _date = new Date(1270544790922);
// outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me
_date.toLocaleString('fi-FI', { timeZone: 'Europe/Helsinki' });
// outputs > "6.4.2010 klo 12.06.30"
_date.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' });
// outputs > "4/6/2010, 12:06:30 PM"

이것은 작동하지만 …. 사용자의 시간대를 설명하기 때문에 목적에 따라 다른 날짜 방법을 실제로 사용할 수 없습니다. 원하는 것은 헬싱키 시간대와 관련된 날짜 개체입니다. 이 시점에서 귀하의 옵션은 타사 라이브러리를 사용하거나 (권장) 날짜 개체를 해킹하여 대부분의 방법을 사용할 수 있도록하는 것입니다.

옵션 1-순간 시간대와 같은 타사

moment(1270544790922).tz('Europe/Helsinki').format('YYYY-MM-DD HH:mm:ss')
// outputs > 2010-04-06 12:06:30
moment(1270544790922).tz('Europe/Helsinki').hour()
// outputs > 12

이것은 우리가 다음에 할 일보다 훨씬 더 우아하게 보입니다.

옵션 2-날짜 개체 해킹

var currentHelsinkiHoursOffset = 2; // sometimes it is 3
var date = new Date(1270544790922);
var helsenkiOffset = currentHelsinkiHoursOffset*60*60000;
var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms]
var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset);
// Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT)

여전히 GMT-0700 (PDT)이라고 생각하지만 너무 세게 쳐다 보지 않으면 목적에 유용한 날짜 개체로 착각 할 수 있습니다.

나는 편리하게 부분을 건너 뛰었다. 정의 할 수 있어야합니다 currentHelsinkiOffset. date.getTimezoneOffset()서버 측에서 사용할 수 있거나 일부 if 문을 사용하여 시간대 변경이 발생할 때를 설명하면 문제가 해결됩니다.

결론 -특히이 목적을 위해 moment-timezone 과 같은 날짜 라이브러리를 사용해야한다고 생각 합니다 .


답변

밀리 초와 사용자의 시간대를 고려하려면 다음을 사용하십시오.

var _userOffset = _date.getTimezoneOffset()*60*1000; // user's offset time
var _centralOffset = 6*60*60*1000; // 6 for central time - use whatever you need
_date = new Date(_date.getTime() - _userOffset + _centralOffset); // redefine variable


답변

또 다른 접근 방식

function parseTimestamp(timestampStr) {
  return new Date(new Date(timestampStr).getTime() + (new Date(timestampStr).getTimezoneOffset() * 60 * 1000));
};

//Sun Jan 01 2017 12:00:00
var timestamp = 1483272000000;
date = parseTimestamp(timestamp);
document.write(date);

건배!


답변

답변 이 올바른 결과를 제공하지 않는다는 의심이 있습니다. 질문에서 asker는 사용자의 현재 시간대를 무시하고 서버에서 Hellsinki의 현재 시간으로 타임 스탬프를 변환하려고합니다.

사용자의 시간대가 될 수 있으므로 우리는 그것을 신뢰할 수 없습니다.

예. 타임 스탬프는 1270544790922이고 함수가 있습니다.

var _date = new Date();
_date.setTime(1270544790922);
var _helsenkiOffset = 2*60*60;//maybe 3
var _userOffset = _date.getTimezoneOffset()*60*60;
var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset);

뉴요커가 페이지를 방문하면 alert (_helsenkiTime)은 다음을 인쇄합니다.

Tue Apr 06 2010 05:21:02 GMT-0400 (EDT)

핀란드 인이 페이지를 방문하면 alert (_helsenkiTime)이 출력합니다.

Tue Apr 06 2010 11:55:50 GMT+0300 (EEST)

따라서 페이지 방문자가 자신의 컴퓨터에 목표 시간대 (Europe / Helsinki)가 있지만 전 세계 거의 모든 지역에서 실패하는 경우에만 기능이 정확합니다. 그리고 서버 타임 스탬프는 일반적으로 Unix Epoch (1970 년 1 월 1 일 00:00:00 GMT) 이후의 시간 인 UTC로 정의 된 UNIX 타임 스탬프이므로 타임 스탬프에서 DST 또는 비 DST를 결정할 수 없습니다.

따라서 해결책은 사용자의 현재 시간대를 무시하고 날짜가 DST인지 여부에 관계없이 UTC 오프셋을 계산하는 방법을 구현하는 것입니다. Javascript에는 사용자의 현재 시간대가 아닌 다른 시간대의 DST 전환 이력을 결정하는 기본 방법이 없습니다. 우리는 모든 시간대의 전체 전환 이력으로 서버의 시간대 데이터베이스에 쉽게 액세스 할 수 있기 때문에 서버 측 스크립트를 사용하여 가장 간단하게이 작업을 수행 할 수 있습니다.

그러나 서버 (또는 다른 서버)의 시간대 데이터베이스에 액세스 할 수없고 타임 스탬프가 UTC 인 경우 Javascript에서 DST 규칙을 하드 코딩하여 유사한 기능을 얻을 수 있습니다.

유럽 ​​/ 헬싱키에서 1998-2099 년의 날짜를 다루기 위해 다음 함수 ( jsfiddled )를 사용할 수 있습니다 .

function timestampToHellsinki(server_timestamp) {
    function pad(num) {
        num = num.toString();
        if (num.length == 1) return "0" + num;
        return num;
    }

    var _date = new Date();
    _date.setTime(server_timestamp);

    var _year = _date.getUTCFullYear();

    // Return false, if DST rules have been different than nowadays:
    if (_year<=1998 && _year>2099) return false;

    // Calculate DST start day, it is the last sunday of March
    var start_day = (31 - ((((5 * _year) / 4) + 4) % 7));
    var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0));

    // Calculate DST end day, it is the last sunday of October
    var end_day = (31 - ((((5 * _year) / 4) + 1) % 7))
    var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0));

    // Check if the time is between SUMMER_start and SUMMER_end
    // If the time is in summer, the offset is 2 hours
    // else offset is 3 hours
    var hellsinkiOffset = 2 * 60 * 60 * 1000;
    if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset =
    3 * 60 * 60 * 1000;

    // Add server timestamp to midnight January 1, 1970
    // Add Hellsinki offset to that
    _date.setTime(server_timestamp + hellsinkiOffset);
    var hellsinkiTime = pad(_date.getUTCDate()) + "." +
    pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() +
    " " + pad(_date.getUTCHours()) + ":" +
    pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds());

    return hellsinkiTime;
}

사용 예 :

var server_timestamp = 1270544790922;
document.getElementById("time").innerHTML = "The timestamp " +
server_timestamp + " is in Hellsinki " +
timestampToHellsinki(server_timestamp);

server_timestamp = 1349841923 * 1000;
document.getElementById("time").innerHTML += "<br><br>The timestamp " +
server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp);

var now = new Date();
server_timestamp = now.getTime();
document.getElementById("time").innerHTML += "<br><br>The timestamp is now " +
server_timestamp + " and the current local time in Hellsinki is " +
timestampToHellsinki(server_timestamp);​

그리고 이것은 사용자 시간대에 관계없이 다음을 인쇄합니다.

The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30

The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23

The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31

물론 오프셋 (DST 또는 비 DST)이 이미 서버의 타임 스탬프에 추가 된 형태로 타임 스탬프를 반환 할 수 있다면 클라이언트 측에서 계산할 필요가 없으며 함수를 많이 단순화 할 수 있습니다. 그러나 timezoneOffset ()을 사용하지 않는 것을 기억하십시오. 사용자 시간대를 처리해야하고 이것은 원하는 동작이 아니기 때문입니다.


답변

헬싱키 시간으로 타임 스탬프를 받았다고 가정하면 1970 년 1 월 1 일 자정 UTC로 설정된 날짜 객체를 만듭니다 (브라우저의 현지 시간대 설정을 무시하기 위해). 그런 다음 필요한 밀리 초를 추가하십시오.

var _date	= new Date( Date.UTC(1970, 0, 1, 0, 0, 0, 0) );
_date.setUTCMilliseconds(1270544790922);

alert(_date); //date shown shifted corresponding to local time settings
alert(_date.getUTCFullYear());    //the UTC year value
alert(_date.getUTCMonth());       //the UTC month value
alert(_date.getUTCDate());        //the UTC day of month value
alert(_date.getUTCHours());       //the UTC hour value
alert(_date.getUTCMinutes());     //the UTC minutes value

날짜 개체에서 항상 UTC 값을 요청하려면 나중에주의하십시오. 이렇게하면 사용자는 로컬 설정에 관계없이 동일한 날짜 값을 볼 수 있습니다. 그렇지 않으면 날짜 값이 현지 시간 설정에 따라 이동됩니다.


답변

당신은 사용할 수 있습니다 setUTCMilliseconds()

var _date = new Date();
_date.setUTCMilliseconds(1270544790922);


답변