programing

자바스크립트에서 시간대 오프셋이 있는 날짜를 ISO 8601 형식으로 지정하는 방법은 무엇입니까?

goodsources 2023. 10. 18. 22:03
반응형

자바스크립트에서 시간대 오프셋이 있는 날짜를 ISO 8601 형식으로 지정하는 방법은 무엇입니까?

목표: 찾기local time그리고.UTC time offset다음 형식으로 URL을 구성합니다.

URL:/Actions/Sleep?duration=2002-10-10T12:00:00−05:00

형식은 W3C 권장사항을 기반으로 합니다.문서에는 다음과 같이 나와 있습니다.

예를 들어 2002-10-10T12:00:00-05:00(2002년 10월 10일 정오, 미국 동부 표준시뿐만 아니라 중부 일광 절약 시간)은 2002-10-10T17:00:00Z와 같으며 이는 2002-10-10T12:00:00Z보다 5시간 늦습니다.

그래서 제가 이해한 바에 따르면, 저는 제 현지 시간을 다음과 같이 구해야 합니다.new Date()그럼 쓰시오getTimezoneOffset()함수를 사용하여 차이를 계산한 다음 문자열 끝에 연결합니다.

  1. 현지 시간 가져오기format

    var local = new Date().format("yyyy-MM-ddThh:mm:ss"); // 2013-07-02T09:00:00
    
  2. UTC 시간 간격띄우기(시간 단위) 가져오기

    var offset = local.getTimezoneOffset() / 60; // 7
    
  3. URL 구성(시간 파트만 해당)

    var duration = local + "-" + offset + ":00"; // 2013-07-02T09:00:00-7:00
    

위의 출력은 현지 시간이 2013/07/02 오전이고 UTC와의 차이가 7시간임을 의미합니다(UTC는 현지 시간보다 7시간 앞서 있음).

지금까지는 효과가 있는 것 같지만 만약에getTimezoneOffset()-120과 같은 음의 값을 반환합니다.

W3C 설명서를 보면 알 수가 없어서 그런 경우에 포맷이 어떻게 되어 있는지 궁금합니다.

여기 JS 데이트를 포맷해 줄 간단한 도우미 기능이 있습니다.

function toIsoString(date) {
  var tzo = -date.getTimezoneOffset(),
      dif = tzo >= 0 ? '+' : '-',
      pad = function(num) {
          return (num < 10 ? '0' : '') + num;
      };

  return date.getFullYear() +
      '-' + pad(date.getMonth() + 1) +
      '-' + pad(date.getDate()) +
      'T' + pad(date.getHours()) +
      ':' + pad(date.getMinutes()) +
      ':' + pad(date.getSeconds()) +
      dif + pad(Math.floor(Math.abs(tzo) / 60)) +
      ':' + pad(Math.abs(tzo) % 60);
}

var dt = new Date();
console.log(toIsoString(dt));

getTimezoneOffset()참조한 규격에 필요한 형식의 반대 기호를 반환합니다.

이 형식은 ISO8601, 더 정확하게는 RFC3339라고도 합니다.

이 형식에서 UTC는 다음과 같이 표시됩니다.Z다른 모든 형식은 UTC로부터의 오프셋으로 표시됩니다.의미는 자바스크립트와 같지만 뺄셈의 순서가 거꾸로 되어 결과가 반대의 부호를 띄고 있습니다.

또한 토종에게는 방법이 없습니다.Date부르는 대상format, 이를 달성하기 위해 라이브러리를 사용하지 않는 한 #1의 함수는 실패합니다.이 설명서를 참조합니다.

이 형식으로 직접 작동할 수 있는 라이브러리를 찾고 있다면 moment.js를 사용해 보는 것을 추천합니다.실제로 이 형식은 기본 형식이므로 다음 작업을 간단히 수행할 수 있습니다.

var m = moment();    // get "now" as a moment
var s = m.format();  // the ISO format is the default so no parameters are needed

// sample output:   2013-07-01T17:55:13-07:00

이 솔루션은 테스트가 잘 완료된 크로스 브라우저 솔루션이며 다른 여러 가지 유용한 기능을 갖추고 있습니다.

표준 라이브러리에 API 호출 한 번으로 요청한 정보를 얻을 수 있다는 점을 고려할 필요가 있다고 생각합니다.

new Date().toLocaleString( 'sv', { timeZoneName: 'short' } );

// produces "2019-10-30 15:33:47 GMT−4"

T' 구분 기호를 추가하거나 'GMT-'를 제거하거나 ':00'을 끝에 추가하려면 텍스트 스왑을 수행해야 합니다.

하지만 당신이 원한다면 다른 옵션들을 쉽게 가지고 놀 수 있습니다.12시간을 사용하거나 초를 생략합니다.

스웨덴은 ISO 8601 형식을 사용하는 국가 중 하나이기 때문에 로케일로 사용하고 있습니다.대부분의 ISO 국가들이 이 'GMT-4' 형식을 시간대 오프셋에 사용하고 있지만, 캐나다는 시간대 약어인 동부-낮의 빛 시간에 "EDT"를 사용하고 있습니다.

최신 표준 i18n 기능 "Intl"에서도 동일한 것을 얻을 수 있습니다.DateTimeFormat()"()"(날짜 시간 형식)을 선택하지만, 선택사항을 통해 시간을 포함하도록 입력해야 합니다. 그렇지 않으면 날짜만 지정됩니다.

제 대답은 YYY-MM-DD 형식의 현지 시간대에서 오늘 날짜만을 원하는 사람들을 위한 약간의 변형입니다.

분명히 말씀드리겠습니다.

목표: 오늘 날짜사용자의 시간대로 가져오되 ISO8601(YYY-MM-DD) 형식으로 지정합니다.

코드는 다음과 같습니다.

new Date().toLocaleDateString("sv") // "2020-02-23" // 

이것은 스웨덴 로케일이 ISO 8601 형식을 사용하기 때문에 작동합니다.

이것이 고객들의 시간대를 위한 나의 기능입니다. 가벼운 무게와 간단한 기능입니다.

  function getCurrentDateTimeMySql() {        
      var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
      var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, 19).replace('T', ' ');
      var mySqlDT = localISOTime;
      return mySqlDT;
  }

확인할 내용:

function dateToLocalISO(date) {
    const off    = date.getTimezoneOffset()
    const absoff = Math.abs(off)
    return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) +
            (off > 0 ? '-' : '+') + 
            Math.floor(absoff / 60).toFixed(0).padStart(2,'0') + ':' + 
            (absoff % 60).toString().padStart(2,'0'))
}

// Test it:
d = new Date()

dateToLocalISO(d)
// ==> '2019-06-21T16:07:22.181-03:00'

// Is similar to:

moment = require('moment')
moment(d).format('YYYY-MM-DDTHH:mm:ss.SSSZ') 
// ==> '2019-06-21T16:07:22.181-03:00'

몇 가지 간단한 확장 방법으로 이를 달성할 수 있습니다.다음 Date extension 메서드는 ISO 형식의 표준 시간대 구성 요소만 반환합니다. 그러면 날짜/시간 부분에 대해 다른 구성 요소를 정의하고 이를 결합하여 전체 날짜-시간-오프셋 문자열을 만들 수 있습니다.

Date.prototype.getISOTimezoneOffset = function () {
    const offset = this.getTimezoneOffset();
    return (offset < 0 ? "+" : "-") + Math.floor(Math.abs(offset / 60)).leftPad(2) + ":" + (Math.abs(offset % 60)).leftPad(2);
}

Date.prototype.toISOLocaleString = function () {
    return this.getFullYear() + "-" + (this.getMonth() + 1).leftPad(2) + "-" +
        this.getDate().leftPad(2) + "T" + this.getHours().leftPad(2) + ":" +
        this.getMinutes().leftPad(2) + ":" + this.getSeconds().leftPad(2) + "." +
        this.getMilliseconds().leftPad(3);
}

Number.prototype.leftPad = function (size) {
    var s = String(this);
    while (s.length < (size || 2)) {
        s = "0" + s;
    }
    return s;
}

사용 예시:

var date = new Date();
console.log(date.toISOLocaleString() + date.getISOTimezoneOffset());
// Prints "2020-08-05T16:15:46.525+10:00"

지금이 2020년이고 대부분의 사람들이 지금쯤 Moment.js를 사용하고 있을 것이라는 것을 알고 있지만, 간단한 복사 및 붙여넣기 솔루션은 여전히 사용하기 편리합니다.

(날짜/시간과 오프셋 방법을 구분한 이유는 이미 유연한 기능을 제공하는 오래된 Datejs 라이브러리를 사용하고 있기 때문입니다.toString사용자 지정 형식 지정자가 있는 method이지만 표준 시간대 오프셋을 포함하지 않습니다.그래서 저는 덧붙였습니다.toISOLocaleString해당 도서관이 없는 모든 사람들을 위해.)

여기 내 돈 2센트만

데이트 시간과 관련된 이 문제에 직면해 있었기 때문에 제가 한 일은 다음과 같습니다.

const moment = require('moment-timezone')

const date = moment.tz('America/Bogota').format()

그런 다음 일부 쿼리에서 날짜를 비교할 수 있도록 db에 저장합니다.


설치하는 방법moment-timezone

npm i moment-timezone

non moment.js need:다음은 입력 유형의 "datetime-local"로부터 GMT에서 UTC 초 단위로 ISOL 로컬 문자열을 출력하는 전체 왕복 답변입니다.

<input type="datetime-local" value="2020-02-16T19:30">

isoLocal="2020-02-16T19:30"
utcSeconds=new Date(isoLocal).getTime()/1000

//here you have 1581899400 for utcSeconds

let isoLocal=new Date(utcSeconds*1000-new Date().getTimezoneOffset()*60000).toISOString().substring(0,16)
2020-02-16T19:30
  • ISO 문자열에 대한 날짜,
  • 로컬(컴퓨터) 시간대와 함께,
  • 밀리초가 있건 없건

ISO ref: https://en.wikipedia.org/wiki/ISO_8601

사용방법: IsoLocalTime(새로운 날짜())

function toIsoLocalTime(value) {
    if (value instanceof Date === false)
        value = new Date();    
    const off = value.getTimezoneOffset() * -1;
    const del = value.getMilliseconds() ? 'Z' : '.'; // have milliseconds ?
    value = new Date(value.getTime() + off * 60000); // add or subtract time zone
    return value
        .toISOString()
        .split(del)[0]
        + (off < 0 ? '-' : '+')
        + ('0' + Math.abs(Math.floor(off / 60))).substr(-2)
        + ':'
        + ('0' + Math.abs(off % 60)).substr(-2);
}

function test(value) {
    const event = new Date(value);
    console.info(value + ' -> ' + toIsoLocalTime(event) + ', test = ' + (event.getTime() === (new Date(toIsoLocalTime(event))).getTime() ));
}

test('2017-06-14T10:00:00+03:00'); // test with timezone
test('2017-06-14T10:00:00'); // test with local timezone
test('2017-06-14T10:00:00Z'); // test with UTC format
test('2099-12-31T23:59:59.999Z'); // date with milliseconds
test((new Date()).toString()); // now

(맷의 대답처럼) 순간을 이용하는 것을 고려합니다.

버전 2.20.0부터는 .toISOstring(true)을 호출하여 UTC 변환을 방지할 수 있습니다.

console.log(moment().toISOString(true));

// sample output:   2022-04-06T16:26:36.758+03:00

시간을 사용합니다.

Temporal.Now.zonedDateTimeISO().toString()
// '2022-08-09T14:16:47.762797591-07:00[America/Los_Angeles]'

분수 초와 IANA 시간대를 생략하려면:

Temporal.Now.zonedDateTimeISO().toString({
  timeZoneName: "never",
  fractionalSecondDigits: 0
})
// '2022-08-09T14:18:34-07:00'

참고: Temporal은 현재(2022년) 폴리필로 제공되고 있지만 곧 주요 브라우저에서 사용할 수 있습니다.

이 목적으로 사용한 기능은 다음과 같습니다.

function localToGMTStingTime(localTime = null) {
    var date = localTime ? new Date(localTime) : new Date();
    return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)).toISOString();
};

function GMTToLocalStingTime(GMTTime = null) {
    var date = GMTTime ? new Date(GMTTime) : new Date();;
    return new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString();
};

럭슨 포함:

DateTime.now().toISODate() // 2022-05-23
let myDate = new Date(dateToBeFormatted * 1000); // depends if you have milliseconds, or seconds, then the * 1000 might be not, or required.
timeOffset = myDate.getTimezoneOffset();
myDate = new Date(myDate.getTime() - (timeOffset * 60 * 1000));

console.log(myDate.toISOString().split('T')[0]);

시간대 오프셋 설명을 포함한 https://stackoverflow.com/a/29774197/11127383, 에서 영감을 얻었습니다.

다음을 얻을 수 있는 간단한 방법

//using a sample date
let iso_str = '2022-06-11T01:51:59.618Z';
let d = new Date(iso_str);

let tz = 'America/Santiago'
let options = {
    timeZone:tz ,
    timeZoneName:'longOffset',
    year: 'numeric',
    month: 'numeric',
    day: 'numeric',
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    fractionalSecondDigits: 3
}


str_locale = d.toLocaleString("sv-SE",options);
iso_str_tz = str_locale.replace(/(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2}),(\d+)\s+/,'$1-$2-$3T$4:$5:$6.$7').replace('GMT−', '-' ).replace('GMT+','+')


console.log('iso_str               : ',iso_str);
console.log('str_locale            : ',str_locale);
console.log('iso_str_tz            : ',iso_str_tz);
console.log('iso_str_tz --> date   : ',new Date(iso_str_tz));
console.log('iso_str_tz --> iso_str: ',new Date(iso_str_tz).toISOString());

사용.moment.js, 사용가능keepOffset의 매개 변수toISOString:

toISOString(keepOffset?: boolean): string;

moment().toISOString(true)

dayjs를 사용한 대체 접근법

import dayjs from "dayjs"

const formattedDateTime = dayjs(new Date()).format()

console.log(formattedDateTime) // Prints 2022-11-09T07:49:29+03:00

오프셋으로 날짜를 변환하는 다른 방법이 있습니다.

function toCustomDateString(date, offset) {
  function pad(number) {
    if (number < 10) {
      return "0" + number;
    }
    return number;
  }

  var offsetHours = offset / 60;
  var offsetMinutes = offset % 60;

  var sign = (offset > 0) ? "+" : "-";
  offsetHours = pad(Math.floor(Math.abs(offsetHours)));
  offsetMinutes = pad(Math.abs(offsetMinutes));

  return date.getFullYear() +
    "-" + pad(date.getMonth() + 1) +
    "-" + pad(date.getDate()) +
    "T" + pad(date.getHours()) +
    ":" + pad(date.getMinutes()) +
    ":" + pad(date.getSeconds()) +
    sign + offsetHours +
    ":" + offsetMinutes;
}

그러면 다음과 같이 사용할 수 있습니다.

var date = new Date();
var offset = 330; // offset in minutes from UTC, for India it is 330 minutes ahead of UTC
var customDateString = toCustomDateString(date, offset);
console.log(customDateString);
// Output: "2023-02-09T10:29:31+05:30"

ISO 형식으로 현재 날짜를 쉽게 얻을 수 있는 원라이너를 찾고 있다면 여기에 있습니다.

const currentIsoDateString = new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString()

Date.now()를 에포크 날짜 정수로 대체하여 다른 날짜의 ISO 날짜/시간 문자열을 가져오도록 변경할 수 있습니다.

이것은 그것이 내부에서 밖으로 작동하는 방법입니다.Date.now()는 1970년 1월 1일 이후 현재 시간(밀리초)을 반환합니다.저는 현재 현지 날짜/시간이 2023-07-05 09:57:32(예:1688565167374)인데 Date.now는 현지 시간은 상관없고, 단지 현지 시간과 상관없이 시대의 시간을 주기 때문에 조정이 필요합니다.

new Date().getTimezonOffset()은 UTC에서 로컬 표준 시간대 오프셋을 반환합니다.저 같은 경우는 240시간이나 4시간입니다.우리는 이 분들에 60000을 곱하여 밀리초로 변환하고 UTC에서 결과를 뺀다.

그러면 핸디 .toISOstring() 네이티브 함수를 사용하여 제대로 포맷된 ISO 문자열을 얻을 수 있습니다.'2023-07-05 T09:58:18.119Z'

라이브러리 필요 없음 :-)

function setDate(){
    var now = new Date();
    now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
    var timeToSet = now.toISOString().slice(0,16);

    /*
        If you have an element called "eventDate" like the following:

        <input type="datetime-local" name="eventdate" id="eventdate" />

        and you would like to  set the current and minimum time then use the following:
    */

    var elem = document.getElementById("eventDate");
    elem.value = timeToSet;
    elem.min = timeToSet;
}

보다 쉬운 또 다른 솔루션을 찾았습니다.

let now = new Date();
// correct time zone offset for generating iso string
now.setMinutes(now.getMinutes() - now.getTimezoneOffset())
now = now.toISOString();

현재 날짜 개체에서 시간대 간격띄우기를 빼서 시간대 간격띄우기를 실행 취소합니다.날짜 개체로부터의 UTC 시간은 이제 현지 시간을 가리키고 있습니다.그러면 현지 시간에 대한 isoidate를 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/17415579/how-to-iso-8601-format-a-date-with-timezone-offset-in-javascript

반응형