从没有时区的日期获取 ISO 字符串

Posted

技术标签:

【中文标题】从没有时区的日期获取 ISO 字符串【英文标题】:Get ISO string from a date without time zone 【发布时间】:2017-09-25 23:22:04 【问题描述】:

我的配置是里斯本时区。当我执行new Date() 时,我会得到我当前的本地日期/时间,即Fri Apr 28 2017 01:10:55 GMT+0100 (GMT Daylight Time)

当我得到带有toISOString() 的 ISO 字符串时,它将应用时区,我会得到:

2017-04-28T00:10:55.964Z

问题是几分钟前的日期时间是这样的(昨天):

2017-04-27T23:45:05.654Z

我尝试了 moment.js(对此是新的)并且我做了类似的事情

document.write(moment('2017-04-28').format())

但我得到这个2017-04-28T00:00:00+01:00 不是2017-04-28T00:00:00.000Z

我想将此值作为 restful 方法的参数传递,以将其自动解析为 DateTime 类型,但如果我传递来自 moment.js 格式的输出,那么它将被解析为 2017-04-27 23:00:00.00

如果我使用new Date()new Date('2017-04-27')(日期部分)创建一个新日期,我只想获得如下 ISO 格式,没有时区:

2017-04-28T00:00:00.000Z

是否有类似 toISOString() 的 javascript 方法或使用可能的时刻来获取该格式?

无论什么时区或一天中的哪个时刻,我只是为了模拟给定日期的午夜。

【问题讨论】:

没有时区的日期/时间值(通常)没有用处,除非时区假定是特定的东西(如 UTC)。这就是你想要的吗? 【参考方案1】:

您可以通过使用moment.format() 简单地格式化您需要的所有内容来实现这一点,然后简单地将额外的 Z 附加到字符串中。您必须在 JS 保留用于输出的时刻内执行此操作。

var date = moment('2014-08-28').format("YYYY-MM-DDT00:00:00.000") + "Z";

小提琴示例https://jsfiddle.net/2avxxz6q/

【讨论】:

感谢您的回答。但它不是输出是 2017-04-27T23:00:00.000Z 而我看的是 2017-04-28T00:00:00.000Z。今天对我来说已经是 4 月 28 日,而不是 4 月 27 日。 如果您不担心时间部分,我更新了我的答案以包含一个替代方案 再次更改并在此处测试输出jsfiddle.net/2avxxz6q@MaximusDecimus【参考方案2】:

不清楚你在问什么。如果您希望 UTC 日期的小时数始终为 0,则将 UTC 小时数设置为 0 并使用 toISOString,例如

var d = new Date();
d.setUTCHours(0,0,0,0);
console.log(d.toISOString());

当然,这将显示 UTC 日期,它可能与生成日期的系统上的日期不同。

还有,

new Date('2017-04-27').toISOString();

应该返回 2017-04-27T00:00:00Z(即它应该根据 ECMA-262 解析为 UTC,这与将其视为本地的 ISO 8601 相悖),但是这在所有使用的实现中并不可靠。

如果您只想获取 ISO 8601 格式的当前日期,您可以这样做:

if (!Date.prototype.toISODate) 
  Date.prototype.toISODate = function() 
    return this.getFullYear() + '-' +
           ('0'+ (this.getMonth()+1)).slice(-2) + '-' +
           ('0'+ this.getDate()).slice(-2);
  


console.log(new Date().toISODate());

但是,由于内置 toISOString 使用 UTC,这可能会造成混淆。如果需要 UTC 日期,则:

if (!Date.prototype.toUTCDate) 
  Date.prototype.toUTCDate = function() 
    return this.getUTCFullYear() + '-' +
           ('0'+ (this.getUTCMonth()+1)).slice(-2) + '-' +
           ('0'+ this.getUTCDate()).slice(-2);
  


console.log(new Date().toUTCDate());

【讨论】:

这对我有帮助。我正在寻找当前客户端的 UTC 日期(没有时区或时间戳)。 对于GetISODate,何不使用更简单的方式:if (!Date.prototype.toISODate) Date.prototype.toISODate = function() return this.toISOString().substring(0,10); 【参考方案3】:

我想您希望获取 ISO 8601 中的当前日期以将其传递给您的 API? 也许对提到的原生 JavaScript 使用 moment.js 包装器 here 可能会有所帮助?

如您的示例:

document.write(moment('01/12/2016', 'DD/MM/YYYY', true).toISOString());

片段:

$(function()
  var displaysTime = $('#divTime');
  displaysTime.text(moment.utc('27/04/2017', 'DD/MM/YYYY', true).toISOString());
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<div id="divTime">
</div>

【讨论】:

【参考方案4】:

我相信你是说你想得到里斯本的当前日期:

moment().tz("Europe/Lisbon").format('YYYY-MM-DD')

您可以看到它按照您认为的方式工作:

moment('2017-04-28T00:00:00+01:00').tz("Europe/Lisbon").format('YYYY-MM-DD') //"2017-04-28"

【讨论】:

【参考方案5】:

您不需要moment.js 库,您只需解析和连接日期组件即可。例如

type Components = 
  day: number,
  month: number,
  year: number


export default class DateFormatter 
  // 2018-11-11T00:00:00
  static ISOStringWithoutTimeZone = (date: Date): string => 
    const components = DateFormatter.format(DateFormatter.components(date))
    return `$components.year-$components.month-$components.dayT00:00:00`
  

  static format = (components: Components) => 
    return 
      day: `$components.day`.padStart(2, '0'),
      month: `$components.month`.padStart(2, '0'),
      year: components.year
    
  

  static components = (date: Date): Components => 
    return 
      day: date.getDate(),
      month: date.getMonth() + 1,
      year: date.getFullYear()
    
  

【讨论】:

虽然您可能不需要时间,但这组代码看起来确实倾向于为 3.2kb gzip 重新制作***,我仍然需要时间。【参考方案6】:

你可以使用https://momentjs.com/docs/#/displaying/as-iso-string/

moment().toISOString(keepOffset);

【讨论】:

【参考方案7】:

你可以试试这个简单的 javascript

(new Date()).toJSON().replace(/\..*$/g,'')

【讨论】:

【参考方案8】:

据我了解,您想要日期开始的 ISOString 与时间无关

(即)时区应该是'T00:00:00.000Z'更多,无论您选择什么日期。

我认为不使用任何插件就没有直接的功能。

所以我创建了一个函数来满足你的需求,如果这是你正在寻找的

function mimicISOString(date) 
    let d = new Date(date),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

    if (month.length < 2) 
        month = '0' + month;
    if (day.length < 2) 
        day = '0' + day;

    return [year, month, day].join('-') +'T00:00:00.000Z';


console.log(mimicISOString(new Date()));

这将返回当前日期以及时区的开始。如果这是您要查找的内容

【讨论】:

【参考方案9】:

如果您希望日期为 UTC 时间 (00:00:00),您可以使用:

moment.utc('2017-04-28').toISOString() // 2017-04-28T00:00:00.000Z

【讨论】:

【参考方案10】:

这里有两个解决方案....

最初,我编写了一小段 JavaScript(好吧,好吧,Typescript),它采用 Date 值并将其转换为 ISO 日期字符串,如下所示:

createDateString(dateStr)      
  //  Take a Date value, and turn it into a "2005-05-26T11:37:42" string
  var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
  var currentDate = new Date(dateStr);
  var withTimezone = new Date(currentDate.getTime() - tzoffset);
  var localISOTime = withTimezone.toISOString().slice(0, 19).replace('Z', '');
  return localISOTime;

这非常有效……直到它被部署到服务器上。然后,我注意到它弄错了时区。

我的解决方案(不求助于第三方产品)是这样重写它:

padZero(numericValue) 
  if (numericValue < 10)
      return '0' + numericValue.toString();;
     
  return numericValue.toString();;

createDateString(date)      
  //  Take a Date value, and turn it into a "2005-05-26T11:37:42" string
  var dateStr = date.getFullYear() + '-' + 
        this.padZero(date.getMonth()+1) + '-' +
        this.padZero(date.getDate()) + 'T' +
        this.padZero(date.getHours()) + ':' + 
        this.padZero(date.getMinutes()) + ':' + 
        this.padZero(date.getSeconds());

  return dateStr;

【讨论】:

【参考方案11】:

old_date = 2021 年 1 月 8 日星期五 16:01:30 GMT+0900

const new_date = old_date.toISOString().substring(0, 10);

new_date = "2021-01-08"

【讨论】:

虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。 请特别讨论为什么您提出的解决方案在最受好评的旧现有答案中讨论的解决方案不可靠。 IE。你的贡献并不新鲜,你必须指出它的优点,而不是当前认为它有缺点的概念。还有另一个较旧的答案,虽然没有被赞成,但它提出的建议与您的相同,只是至少带有一些信息的链接。复制其他答案,或因缺乏阅读现有答案而重新发布它们,在这里不受欢迎,因为它不会为 Q/A 集合提供额外的价值。 只是想在这里提供一个简单的解决方案。我没有太多时间,绝对没有从别人那里复制粘贴。如果事实上没有像我上面那样给出答案,尽管再次阅读,有人在 cmets 中放了类似的东西。如果您有比我更多的时间,请随意编辑它以添加解释,如果没有,我会将它留在这里给任何可能觉得它有用的人(并且没有太多时间阅读原因的解释)我的解决方案比其他任何解决方案更好或更差) 这一行非常清晰,任何 JavaScript 开发人员都知道发生了什么。简单有效,它只是删除了日期字符串中不需要的时间字符。我想知道为什么以前没有人提出过这个解决方案。我看不到据报道该解决方案已经回答的旧答案。 不过我同意它需要进一步的造型润色。第一行和最后一行应该是代码块的一部分。第一行:const old_date = new Date("Fri Jan 08 2021 16:01:30 GMT+0900");。最后一行:console.log(new_date); // "2021-01-08"。而且,即使解决方案是不言自明的,单行介绍也能更好地展示解决方案。【参考方案12】:

我写了一个扩展moment js对象的简单函数:

moment.fn.toISOStringWithoutTimezone = function () 
  return this.format("YYYY-MM-DD[T]HH:mm:ss");
;

可以这样使用

moment().toISOStringWithoutTimezone();

【讨论】:

【参考方案13】:

你可以试试这个,它对我有用! 您将拥有 ISO 格式 没有 timeZone 效果

2021 年 1 月 1 日星期五 23:10:00 GMT+0100 => 2021-01-01T23:10:00.000Z

function isoDateWithoutTimeZone(date) 
  if (date == null) return date;
  var timestamp = date.getTime() - date.getTimezoneOffset() * 60000;
  var correctDate = new Date(timestamp);
  // correctDate.setUTCHours(0, 0, 0, 0); // uncomment this if you want to remove the time
  return correctDate.toISOString();



        var now= new Date("01-01-2021 23:10:00");
        console.log(now.toString());
        var returnedDate = isoDateWithoutTimeZone(now);
        console.log(returnedDate);

【讨论】:

【参考方案14】:

我的问题:我需要一直将日期和时间以 ISO 格式发送到服务器 API。 为了解决这个问题,我可以简单地使用 new Date().toISOString() 但我的客户端应用程序可能在不同的时区运行,因此时区始终存在差异。

解决方案:为了解决这个问题,我参考了上面给出的解决方案,即不管给定时区,手动创建 ISO 格式字符串。

function getISOString(date)

let d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = ''+ d.getFullYear(),
hours = ''+d.getHours(),
minutes = ''+d.getMinutes(),
seconds = ''+d.getSeconds();
month = month.length < 2? '0' + month : month;
day   = day.length < 2? '0' + day : day;
hours = hours.length < 2?'0'+hours:hours;
minutes = minutes.length< 2? '0'+minutes:minutes;
seconds = seconds.length< 2? '0'+seconds:seconds;
return ( [year, month, day].join('-')+'T'+[hours,minutes,seconds].join(':')+'.000');

console.log(getISOString(new Date()));

【讨论】:

【参考方案15】:

new Date('2019-04-27').toISOString();

你也可以使用dayjs:https://day.js.org/

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review

以上是关于从没有时区的日期获取 ISO 字符串的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 从 ISO8601 日期字符串中检索时区

将iso日期格式的字符串转换为毫秒。 ISO日期格式包含(“ yyyy-MM-dd”),并且没有时区

将 ISO 8601 日期时间字符串转换为 **Date** 对象时,如何将日期时间重新定位到当前时区?

如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?

如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?

识别 ISO 8601 中的时区