Дата розбору без JavaScript


147

Я хочу проаналізувати дату без часового поясу в JavaScript. Я намагався:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

Повертається Пт 08 липня 2005 02:00:00 GMT + 0200 (Центральноєвропейський літній час)

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

Повертає той самий результат

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

Повертає той самий результат

Я хочу проаналізувати час:

  1. Без часового поясу.

  2. Без виклику конструктора Date.UTC або нової дати (рік, місяць, день).

  3. Просто простий рядок, що передається в конструктор дат (без прототипу підходів).

  4. Я повинен Dateоб'єкт продукту , а не String.


3
Ви можете просто опустити Date.parsebtw і безпосередньо передати рядок Dateконструктору.
Бергі

1
Я не впевнений, навіщо це вам потрібно, але я впевнений, що Дата завжди має місцевий часовий пояс користувача. Якщо ви хочете, щоб ваш JavaScript працював з іншими часовими поясами,
HMR

1
На жаль, мені довелося скопіювати Dateоб’єкт, щоб отримати правильний об’єкт, щоб порівняти дати в MongoDB:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
Athlan

Якщо ви хочете проаналізувати дату без часу, вам потрібно вказати, який часовий пояс ви хочете припустити, оскільки "2005-07-08" означає різні речі в різних часових поясах. Станом на травень 2020 року документація MDN не рекомендує застосовувати будь-які функції розбору дат вбудованого періоду через відмінності в реалізації. Однак використання Date.parse ("2005-07-08"), ймовірно, поверне час 00:00 UTC. Дата-fns розбору, з іншого боку, повернеться 00:00 за місцевим часом при синтаксичному аналізуванні рядків тієї ж дати
Енді

Відповіді:


106

Дата правильно проаналізована, вона просто toString перетворює її у ваш локальний часовий пояс:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Об'єктом дати JavaScript є часові позначки - вони просто містять кількість мілісекунд з епохи. Інформація про часовий пояс в об’єкті дати Яку календарну дату (день, хвилини, секунди) представляє ця часова мітка - це питання тлумачення (один із to...Stringметодів).

Наведений вище приклад показує, що дату розбирають правильно - тобто вона фактично містить кількість мілісекунд, що відповідає "2005-07-08T11: 22: 33" в GMT.


4
На жаль, я повинен створити об'єкт Date, а не String.
Атлан

@Athlan: додав пояснення.
georg

1
Я це перевірив. Я пройшов розібрану дату в MongoDB запит new Date(Date.parse("2005-07-08T11:22:33+0000")), дата і скопійований з допомогою конструктора: new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate()). Обидва рішення, різні результати, друге правильне! Ваша відповідь була корисною, щойно згадується в hunlock.com/blogs/Javascript_Dates-The_Complete_Reference . Вгору
Атлан

Для мене прекрасно працював - .toUTCString () - це квиток, який дав мені правильний час назад від початкового даного рядка. тобто нова дата ("2016-08-22T19: 45: 00.0000000".) toUTCString ()
Michael Giovanni Pumo

38
Корінь усякого зла в датах і часі JavaScript міститься у вашому першому реченні ... Це просто, щоб стверджувати, що ПЕРЕВІРТЕ його у свій місцевий часовий пояс ... Де в цьому є одна відповідальність? Метод toString повинен просто підкреслити результат, а не перетворити його. Якщо я хочу перетворити дату, у мене повинні бути інші методи для цього.
якір

109

У мене те саме питання. Я отримую дату у вигляді рядка, наприклад: '2016-08-25T00: 00: 00', але мені потрібно мати об’єкт Date з правильним часом. Для перетворення String в об'єкт використовую getTimezoneOffset:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset()поверне ефіру негативне або позитивне значення. Це потрібно відняти для роботи в будь-якій точці світу.


6
У мене є те саме питання, і це стало корисним. Однак я виявив, що це не справляється зі зміщенням часового поясу через літній час. Приклад: я в PST, тому моє поточне зміщення (у березні) від GMT становить -8: 00, але в травні це буде -7: 00. Моїм рішенням було обчислитиvar userTimezoneOffset = date.getTimezoneOffset()*60000;
mmh02

3
Якщо я не повний ідіот, це насправді повертає неправильний час. getTimezoneOffset()повертає кількість хвилин у зворотному напрямку, який ви могли б подумати - мій часовий пояс зараз UTC-4, але getTimezoneOffset()повертає позитивне 240. Тому userTimezoneOffsetслід відняти date.getTime(), а не додавати до нього.
vaindil

1
Я погоджусь з @vaindil, який ви повинні субстратувати. Рішення wakwa працює лише тоді, коли ви правильна сторона Грінвіч. Wakwas повинен це виправити.
Janne Harju

1
Ах! заговорили занадто рано. Він не працює для більшості часових поясів. Я можу підтвердити, що він повертає неправильну дату при зміщенні AEST & CEST разів на час GMT.
saran3h

1
@vaindil зараз результат такий же, як new Date('2016-08-25T00:00:00Z')я думаю, що справа полягала в new Date('2016-08-25T00:00:00Z')тому, щоб маніпулювати таким чином, щоб місцевий час відображався з часом 0:00, але цей код пропущеноZ
barbsan

14

Я зіткнувся з тією ж проблемою, а потім згадав щось примхливе про спадковий проект, над яким я працював, і як вони вирішували це питання. Я цього не розумів і не дуже хвилювався, поки сам не зіткнувся з проблемою

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

З будь-якої причини, передаючи дату як '01 -02-2014 ', часовий пояс встановлюється на нуль і ігнорує часовий пояс користувача. Це може бути динаміка в класі Date, але вона існувала деякий час тому і існує сьогодні. І, здається, працює крос-браузер. Спробуйте самі.

Цей код реалізований у глобальному проекті, де часові пояси мають велике значення, але людина, яка дивиться на дату, не переймалася точним моментом його введення.


Я думаю, що це навмисно, оскільки "Z" позначає UTC, який JS потім перетворює, але, враховуючи відсутність часового поясу, він не може його перетворити, тому він по суті передбачає часовий пояс користувача. Хочеться отримати підтвердження або краще пояснення.
dlsso

7
Вибаглива поведінка пояснюється тире. Chrome, Firefox і IE11 все інтерпретують 2014/5/31і 2014/05/31як Сб 31 травня 2014 00:00:00 GMT-0600 (гірський літній час) `(МДТ - мій поточний часовий пояс). З тире ... всі браузери трактують 2014-05-31як Пт 30 травня 2014 18:00:00 GMT-0600 (гірський літній час). Як не дивно, 2014-5-31Chrome повертається в суботу, Firefox повертається в п'ятницю, а IE11 каже, що дата недійсна. Здається, це date.replace('-','/')може зробити трюк.
atheaos

6

Сам Dateоб’єкт все одно буде містити часовий пояс, а повернутий результат - це ефект перетворення його на рядок за замовчуванням. Тобто ви не можете створити об’єкт дати без часового поясу. Але те, що ти можеш зробити, це імітувати поведінку Dateоб’єкта, створюючи свій власний. Це, однак, краще передавати в такі бібліотеки, як moment.js .


2
На жаль, я повинен створити об'єкт Date, а не String.
Атлан

3

просте рішення

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);

3

Дата в JavaScript просто зберігає її простою всередині. тому дані про дату та час зберігаються в епоху UTC unix (мілісекунд або мс).

Якщо ви хочете мати "фіксований" час, який не змінюється в будь-який часовий пояс на землі, ви можете налаштувати час у UTC відповідно до вашого поточного місцевого часового поясу та зберегти його. І коли його буде відновлено, у будь-якому місцевому часовому поясі ви знаходитесь, він покаже скоригований час UTC на основі того, хто його врятував, і додасть локальний зсув часового поясу, щоб отримати "фіксований" час.

Для збереження дати (в мс)

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

Відновлення / показ дати (в мс)

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

Тоді ви можете:

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));

2

Ви можете використовувати цей код

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);

1
Я не вірю, що це враховує економію денного світла
Даніель Томпсон

2

Оскільки це справді проблема з форматуванням під час відображення дати (наприклад, відображається за місцевим часом), я люблю використовувати новий (ish) Intl.DateTimeFormat об’єкт для виконання форматування, оскільки воно є більш явним і забезпечує більше варіантів виводу:

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

Як показано, встановивши timeZone на "UTC", він не здійснюватиме місцеві перетворення. Як бонус, він також дозволяє створювати більше відшліфованих результатів. Ви можете прочитати більше про об’єкт Intl.DateTimeFormat від Mozilla - Intl.DateTimeFormat .

Редагувати:

Такої ж функціональності можна досягти без створення нового Intl.DateTimeFormatоб’єкта. Просто перенесіть параметри локалі та дати безпосередньо у toLocaleDateString()функцію.

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
today.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"

1

Просто родова нота. спосіб зберегти його гнучким.

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

Ми можемо використовувати getMinutes (), але він повертає лише одне число протягом перших 9 хвилин.

let epoch = new Date() // Or any unix timestamp

let za = new Date(epoch),
    zaR = za.getUTCFullYear(),
    zaMth = za.getUTCMonth(),
    zaDs = za.getUTCDate(),
    zaTm = za.toTimeString().substr(0,5);

console.log(zaR +"-" + zaMth + "-" + zaDs, zaTm)

Date.prototype.getDate()
    Returns the day of the month (1-31) for the specified date according to local time.
Date.prototype.getDay()
    Returns the day of the week (0-6) for the specified date according to local time.
Date.prototype.getFullYear()
    Returns the year (4 digits for 4-digit years) of the specified date according to local time.
Date.prototype.getHours()
    Returns the hour (0-23) in the specified date according to local time.
Date.prototype.getMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to local time.
Date.prototype.getMinutes()
    Returns the minutes (0-59) in the specified date according to local time.
Date.prototype.getMonth()
    Returns the month (0-11) in the specified date according to local time.
Date.prototype.getSeconds()
    Returns the seconds (0-59) in the specified date according to local time.
Date.prototype.getTime()
    Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC (negative for prior times).
Date.prototype.getTimezoneOffset()
    Returns the time-zone offset in minutes for the current locale.
Date.prototype.getUTCDate()
    Returns the day (date) of the month (1-31) in the specified date according to universal time.
Date.prototype.getUTCDay()
    Returns the day of the week (0-6) in the specified date according to universal time.
Date.prototype.getUTCFullYear()
    Returns the year (4 digits for 4-digit years) in the specified date according to universal time.
Date.prototype.getUTCHours()
    Returns the hours (0-23) in the specified date according to universal time.
Date.prototype.getUTCMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to universal time.
Date.prototype.getUTCMinutes()
    Returns the minutes (0-59) in the specified date according to universal time.
Date.prototype.getUTCMonth()
    Returns the month (0-11) in the specified date according to universal time.
Date.prototype.getUTCSeconds()
    Returns the seconds (0-59) in the specified date according to universal time.
Date.prototype.getYear()
    Returns the year (usually 2-3 digits) in the specified date according to local time. Use getFullYear() instead. 

-1

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Це матиме вихід: вт 10 липня 2018 19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

Це матиме вихід: Пт 08 липня 2005 04:22:33

Примітка: повернутий час залежатиме від місцевого часового поясу


-1

Це рішення, яке я придумав для цієї проблеми, яка працює для мене.


використовувана бібліотека: momentjs з простим класом дати JavaScript.

Крок 1. Перетворіть дату рядка в об'єкт моменту (PS: момент зберігає початкову дату та час, доки toDate()метод не буде викликаний):

const dateMoment = moment("2005-07-08T11:22:33+0000");

Крок 2. Витяг hoursі minutesзначення з створеного раніше об'єкта моменту:

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

Крок 3. Перетворіть момент у дату (PS: це змінить початкову дату залежно від часового поясу вашого браузера / машини, але не хвилюйтеся та прочитайте крок 4.):

  const dateObj = dateMoment.toDate();

Крок 4. Вручну встановіть години та хвилини, витягнуті на етапі 2.

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

Крок 5. dateObj тепер буде показана початкова дата без різниці в часовому поясі. Навіть зміни літнього часу не матимуть ніякого впливу на об’єкт дати, оскільки ми вручну встановлюємо початкові години та хвилини.

Сподіваюся, це допомагає.


-7

Є деякі притаманні проблеми з розбором дат, які, на жаль, не вирішуються за замовчуванням.

-Читання, що читаються людиною, має в них неявний часовий пояс.
- В Інтернеті існує багато широко використовуваних форматів дат, які є неоднозначними

Щоб вирішити ці проблеми легко і просто, потрібна така функція:

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

Я шукав це, але нічого подібного не знайшов!

Так я створив: https://github.com/zsoltszabo/timestamp-grabber

Насолоджуйтесь!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.