Как сохранить часовой пояс даты JavaScript от браузера к серверу и обратно?

Например, используя элемент управления датой и временем, пользователь выбирает дату и время, так что строковое представление выглядит следующим образом:

"6-25-2012 12:00:00 PM"

Так получилось, что этот пользователь находится в часовом поясе EST. Строка передается на сервер, который переводит его в объект .NET DateTime, а затем сохраняет его в SQL Server в столбце datetime.

Когда дата возвращается позже в браузер, ее необходимо преобразовать обратно в дату, однако, когда указанная строка будет отправлена ​​на дату, она теряет 4 часа. Я считаю, что это связано с тем, что, когда вы не указываете часовой пояс при создании даты JavaScript, он по умолчанию использует локальное время, и поскольку EST составляет -400 по Гринвичу, он вычитает 4 часа с 12 часов вечера, даже если этот 12pm должен был быть указан как EST, когда пользователь выбрал его на машине в часовом поясе EST.

Ясно, что что-то должно быть добавлено к исходной строке datetime до того, как оно будет передано на сервер, чтобы быть сохраненным. Каков рекомендуемый способ сделать это?

Ответ 1

Не используйте конструктор JavaScript Date для синтаксического анализа строки. Поведение и поддерживаемые форматы сильно различаются для каждого браузера и локали. Здесь - это лишь некоторые из вариантов поведения по умолчанию, если вы напрямую используете объект Date.

Если вы должны исходить из строки, попробуйте использовать стандартизованный формат, такой как ISO8601. Дата, указанная в этом формате, будет "2012-06-25T12:00:00". Самый простой способ работы с ними в JavaScript - moment.js.

Кроме того, будьте осторожны с тем, что вы на самом деле имеете в виду. Прямо сейчас вы проходите локальную дату/время, сохраняя локальный/дата/время и возвращая локальную дату/время. По пути идея "локального" может измениться.

Во многих случаях дата/время предназначены для точного момента. Чтобы выполнить эту работу, вам необходимо преобразовать с локального времени, введенного в UTC на клиенте. Отправьте UTC на свой сервер и сохраните его. Позже, получите UTC и отправьте его обратно своему клиенту, обработайте его как UTC и переведите обратно в локальное время. Вы можете сделать все это легко с помощью moment.js:

// I'll assume these are the inputs you have.  Adjust accordingly.
var dateString = "6-25-2012";
var timeString = "12:00:00 PM";

// Construct a moment in the default local time zone, using a specific format.
var m = moment(dateString + " " + timeString, "M-D-YYYY h:mm:ss A");

// Get the value in UTC as an ISO8601 formatted string
var utc = m.toISOString(); // output: "2012-06-25T19:00:00.000Z"

На сервере в .Net:

var dt = DateTime.Parse("2012-06-25T19:00:00.000Z",   // from the input variable
                        CultureInfo.InvariantCulture, // recommended for ISO
                        DateTimeStyles.RoundtripKind) // honor the Z for UTC kind

Сохраните это в базе данных. Позже верните его и отправьте обратно:

// when you pull it from your database, set it to UTC kind
var dt = DateTime.SpecifyKind((DateTime)reader["yourfield"], DateTimeKind.Utc);

// send it back in ISO format:
var s = dt.ToString("o"); // "o" is the ISO8601 "round-trip" pattern.

Передайте его обратно в javascript в moment.js:

// construct a moment:
var m = moment("2012-06-25T19:00:00.000Z"); // use the value from the server

// display it in this user local time zone, in whatever format you want
var s = m.format("LLL");   // "June 25 2012 12:00 PM"

// or if you need a Date object
var dt = m.toDate();

Смотрите - это было легко, и вам не нужно было вовлекаться в часовые пояса.

Ответ 2

Здесь, я думаю, это то, что вы ищете: Как игнорировать часовой пояс пользователя и заставить Date() использовать определенный часовой пояс

Мне кажется, что вы можете сделать что-то вроде этого:

var date = new Date("6-25-2012 12:00:00 PM");

var offset = date.getTimezoneOffset(); // returns offset from GMT in minutes

// to convert the minutes to milliseconds
offset *= 60000;

// the js primitive value is unix time in milliseconds so this retrieves the 
// unix time in milliseconds and adds our offset.
// Now we can put this all back in a date object
date = new Date(date.valueOf() + offset);

// to get back your sting you can maybe now do something like this:
var dateString = date.toLocaleString().replace(/\//g,'-').replace(',','');

Ответ 3

Я использую фильтр перед отправкой даты на сервер vm.dateFormat = 'yyyy-MM-dd'; dateToSendToServer = $filter ('date') (dateFromTheJavaScript, vm.dateFormat);