从日期时间字符串获取偏移量并将其应用于新的日期对象

时间:2018-12-30 23:23:42

标签: javascript date datetime object momentjs

我有一个从后端返回的datetime字符串,如下所示:

2018-12-30T20:00:00-05:00

我正在尝试从此datetime字符串获取偏移量并将其应用于新的Date对象。

这样做的时候...我得到的是客户的时区日期,而不是我想要的日期。

var time = "2018-12-30T20:00:00-05:00"
new Date(time)

我不介意利用momentjs或JS中的任何其他库,但我正在尝试在前端进行此操作。

更新

如果从后端返回的日期的偏移量为-05:00,那么当我在前端创建日期对象时,它应该具有相同的偏移量

例如:

2018-12-31T10:00:00-05:00

3 个答案:

答案 0 :(得分:3)

如果您愿意使用moment,则可以使用utcOffset轻松地从日期/时间获取偏移量。您可以使用相同的功能将偏移量应用于新的日期/时间。这是两个表示相同时间但具有不同偏移量的矩对象。它将第二个转换为第一个的偏移量而不更改绝对时间:

var time = "2018-12-30T10:00:00-05:00"
let m = moment.parseZone(time)
let offset = m.utcOffset()
console.log("original: ", m.format(), "Offset:", offset)

// same time as m but -1 ofset
let m2 = moment.parseZone("2018-12-30T14:00:00-01:00")
console.log("m2 original: ", m2.format())

// change offset
m2.utcOffset(offset)
console.log("m2 converted: ", m2.format())
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>

答案 1 :(得分:1)

对于那些不愿使用Moment JS的人,这是一个非常粗糙的示例,说明了如何使用纯JS进行处理:

const d = new Date("2018-12-30T20:00:00-05:00");
const epochTimeDate = d.getTime(); // Get milliseconds since Unix Epoch
const localTZOffsetMilliseconds = d.getTimezoneOffset() * (60 * 1000); // Convert minutes to milliseconds
const msCoefficient = (60 * 60 * 1000);
const newTZOffsetHours = -3; // UTC -3

const newTZTime = new Date(epochTimeDate - (-1*(newTZOffsetHours*msCoefficient))); // The -1 reverses the confusing behavior of the browser spec which is the opposite of the actual offset
console.log(newTZTime.toISOString().replace(/T|Z/g,' ')+"(UTC "+newTZOffsetHours+")");

更好的输出方式是使用自己的函数,使用getter函数显示日期,以显示小时,分钟等。我不确定.toISOString()是否为标准,但它可以在Chrome中使用。

答案 2 :(得分:1)

您需要从字符串中获取时区,将其转换为ECMAScript偏移量,然后使用它来格式化具有所需偏移量的字符串。

上面已经有答案可以解决上述问题,但是无论如何这都是答案。

例如

/* Returns offset, uses match to allow for decimal seconds in timestamp
** @param {string} s - ECMAScript formatted datetime string with offset
**                    in the format YYYY-MM-DDTHH:mm:ss+/-HH:mm or Z
** @returns {string} - offset part of string, i.e. +/-HH:mm or Z
*/
function getOffset(s) {
  return offset = (s.match(/z$|[+\-]\d\d:\d\d$/i) || [])[0];
}

/* Convert offset in +/-HH:mm format or Z to ECMAScript offset
** @param {string} offset - in +/-HH:mm format or Z
** @returns {number} - ECMSCript offset in minutes, i.e. -ve east, +ve west
*/
function offsetToMins(offset) {
  // Deal with Z or z
  if (/z/i.test(offset)) return 0;
  // Deal +/-HH:mm
  var sign = /^-/.test(offset)? '1':'-1';
  var [h, m] = offset.slice(-5).split(':');
  return sign * h * 60 + +m; 
}

/* Format date with offset
** @param {Date} date - date to format
** @param {string} offset - ECMASCript offset string, 
**                          e.g. -05:00, Z
** @returns {string} ISO 8601 formatted string with
** specified offset
*/
function adjustToOffset(date, offset) {
  var o = offsetToMins(offset);
  var d = new Date(+date);
  d.setUTCMinutes(d.getUTCMinutes() - o);
  return d.toISOString().replace('Z', offset);
}

// Source string
var s = '2018-12-30T20:00:00-05:00';

// Get offset
var offset = getOffset(s);

// Make sure it's ok
if (typeof offset == 'undefined') {
  console.log('offset not found');

// Otherwise, show current time with specified offset
} else {
  console.log(adjustToOffset(new Date(), offset));
}

请注意,典型的ISO 8601偏移量没有冒号,即通常为±HHmm。