【问题标题】:How using humanized date can I get localized duration in JS?如何使用人性化日期在 JS 中获得本地化的持续时间?
【发布时间】:2021-03-02 01:57:11
【问题描述】:

我有以下 JSON 日期对象:

[
  {
    "date_start": "septembre 2019",
    "date_end": "septembre 2020"
  },
  {
    "date_start": "juin 2017",
    "date_end": "avril 2019"
  },
  {
    "date_start": "novembre 2015",
    "date_end": "Aujourd'hui"
  },
  {
    "date_start": "novembre 2012",
    "date_end": "février 2015"
  },
  {
    "date_start": "novembre 2011",
    "date_end": "octobre 2012"
  }
]

我想将这些人性化日期转换为en_USfr_FR 中的本地化持续时间。

这是en_US 的预期结果

持续时间语法不必严格地是本示例中的语法!

[
  {
    "date_start": "september 2019",
    "date_end": "september 2020",
    "duration": "1 yrs 1 mo"
  }
]

我正在查看date-fns,但到目前为止我还没有找到方法。 (我还检查了momentjs)。

有人知道我可以如何在人性化的持续时间内转换它们吗?我认为这应该首先转换为日期。

【问题讨论】:

    标签: javascript date momentjs moment-timezone date-fns


    【解决方案1】:

    你可以使用这个简单的纯JS代码。

    它是如何工作的:

    frStringToDate() 函数将您的字符串转换为 Date 对象。它首先检查字符串格式,然后从中获取法语月份名称和年份。然后它(使用months 对象)将法语月份名称转换为英语 3 字符月份缩写,最终为Date 构造函数创建可读字符串。

    calculateDuration() 函数减去两个日期并将结果(以毫秒为单位)“转换”为Date 对象。众所周知,new Date(0)Jan 1, 1970,所以我们可以从结果Date 对象的年份中减去1970。为了得到月份,我们需要将1添加到.getMonth()函数的结果中,因为月份从0开始编号。然后我们可以返回结果字符串。

    getDurationFromObj() 只是为了代码可读性

    const months = {
      'janvier': 'jan',
      'février': 'feb',
      'mars': 'mar',
      'avril': 'apr',
      'mai': 'may',
      'juin': 'jun',
      'juillet': 'jul',
      'août': 'aug',
      'septembre': 'sep',
      'octobre': 'oct',
      'novembre': 'nov',
      'décembre': 'dec'
    }
    
    const dates = [{
        "date_start": "septembre 2019",
        "date_end": "septembre 2020"
      },
      {
        "date_start": "juin 2017",
        "date_end": "avril 2019"
      }
    ]
    
    function frStringToDate(frDateString) {
      const matched = frDateString.match(/^(\w+) (\d{4})$/)
      if (matched) {
        const frMonth = matched[1]
        const year = matched[2]
    
        const enMonth = months[frMonth]
        if (!enMonth) return null
    
        return new Date(`${enMonth}  ${year}`)
      }
      return null
    }
    
    function calculateDuration(date1, date2) {
      const durationMillis = date1 < date2 ? date2 - date1 : date1 - date2
      const durationDate = new Date(durationMillis)
      const years = durationDate.getFullYear() - 1970
      const months = durationDate.getMonth() + 1
    
      return `${years} yrs ${months} mo`
    }
    
    function getDurationFromObj(obj) {
      const date1 = frStringToDate(obj.date_start)
      const date2 = frStringToDate(obj.date_end)
      return calculateDuration(date1, date2)
    }
    
    dates.forEach(obj => console.log(getDurationFromObj(obj)))

    【讨论】:

    • 感谢您的回复,我在 node.js 环境中,所以我不介意使用重量为 10mb 的可靠库,我怀疑它会。此外,即使我目前只需要fr_FRen_US,我也担心自己使用这种方式进行所有本地化。仍然感谢您的回复。
    • 解析一个字符串以创建另一个字符串然后由内置解析器解析似乎既不明智也不高效,尤其是当第二个操作的结果完全依赖于实现时。至少在 Safari 中,new Date('sep 2020') 会导致日期无效。将月份名称解析为等效的月份编号并使用整数值(例如 new Date(2020, 8))调用日期构造函数会更好,这符合标准,并且将在所有实现中产生可靠且一致的结果。
    猜你喜欢
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 2021-09-20
    • 2012-08-10
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    相关资源
    最近更新 更多