[Day07] Vue i18n - Datetime Formatting

在本地化 (localize) 专案时,我们可能会遇到需要处理日期时间显示的问题,因为日期时间的显示方式可能会因为每个国家而有所不同,例如:

<p>Apr 19, 2017</p>
<p>2017年4月19日(水) 午前2:19</p>

所以今天我们要来分享的就是 vue i18n 可以帮我们达到这件事的 Datetime Formatting,事实上 Datetime Formatting 背後的实践方式是透过原生 JS 的 Intl.DateTimeFormat 来做到的,所以 Datetime Formatting 所拥有的属性基本上和 Intl.DateTimeFormat 是一样的。

属性选项

这里我们只针对常使用的属性做介绍,详细完整的可参考 Intl.DateTimeFormat() constructor

dateStyle 要使用的日期格式样式

  • long - September 9, 2021
  • medium - Sep 9, 2021
  • short - 9/9/21

timeStyle 要使用的时间格式样式

  • full - at 5:43:38 AM Taipei Standard Time
  • long - at 5:43:38 AM GMT+8
  • medium - 5:43:38 AM
  • short - 5:43 AM

timeZone 要使用的时区,例如 Asia/Taipei ,完整的时区名称可以参考 List of tz database time zones

hour12 是否使用 12 小时制,反之则为 24 小时制。

weekday 工作日的显示格式

  • long - Thursday
  • short - Thu
  • narrow - T

year 年份的显示格式

  • numeric - 2021
  • 2-digit - 21

month 月份的显示格式

  • numeric - 9
  • 2-digit - 09
  • long - September
  • short - Sep
  • narrow - S

day 日期的显示格式

  • numeric - 9
  • 2-digit - 09

hour 小时的显示格式

  • numeric - 9
  • 2-digit - 09

minute 分钟的显示格式,选项和 hour 相同

second 秒钟的显示格式,选项和 hour 相同

需要特别注意的是,如果设定了 dateStyle 或是 timeStyle 就不能再设定 weekday, year, month, day, hour, minute 和 second ,但两者是可以同时设定的。

基本用法

datetime formatting 所使用的 translation api 是 $d(value, key, locale)

  • value - 要本地化的数值。
  • key - 指的是 en 物件下一层自己的 key,如下面程序码中的 short 或 long。
  • locale - 指定要用哪一个语系来本地化,预设会是全局的 locale 值。
export default createI18n({
  ...,
  datetimeFormats: {
	en: {
	  short: {
	    year: 'numeric',
	    month: 'short',
	    day: 'numeric'
	  },
	  long: {
	    year: 'numeric',
	    month: 'short',
	    day: 'numeric',
	    weekday: 'short',
	    hour: 'numeric',
	    minute: 'numeric'
	  }
	}
}})

所以在 template 的写法会是:

<p>{{ $d(new Date(), 'short') }}</p>
<p>{{ $d(new Date(), 'long') }}</p>

得到的结果是:

<p>Sep 9, 2021</p>
<p>Thu, Sep 9, 2021, 6:28 AM</p>

Custom Formatting

由於 $d 会直接回传格式化的字串结果,我们只能作为一整体去使用,但有的时候我们会需要针对其中一部分去设定不同的样式,所以为了应对这种情况 vue i18n 有提供我们 NumberFormat 组件 (i18n-d) 来达到这件事。

i18n-d 的基本用法如下。 (此时得到的结果和用 $d 的结果一样)

<i18n-d tag="span" :value="new Date()" format="long" locale="en">

i18n-d 有四个 props :

tag 选择根节点的 HTML tag。

value 要本地化的日期时间值。

format 选用哪一个定义好的格式的 key (同 $d(value, key) 中的 key)。

locale 指定要用哪一个语系来本地化,预设会是全局的 locale 值。

如果想要个别控制每一个部分做到上面图示中的样子,我们要透过 slots 的方式,像是:

<i18n-d tag="span" :value="new Date()" format="long">
  <template #year="props">
    <span class="year">{{ props.year }}</span>
  </template>
  <template #month="props">
    <span class="month">{{ props.month }}</span>
  </template>
  <template #day="props">
    <span class="day">{{ props.day }}</span>
  </template>
  <template #weekday="props">
    <span class="weekday">{{ props.weekday }}</span>
  </template>
  <template #hour="props">
    <span class="hour">{{ props.hour }}</span>
  </template>
  <template #minute="props">
    <span class="minute">{{ props.minute }}</span>
  </template>
  <template #literal="props">
    <span class="literal">{{ props.literal }}</span>
  </template>
  <template #dayPeriod="props">
    <span class="dayPeriod">{{ props.dayPeriod }}</span>
  </template>
</i18n-d>

这样得到的结果会是

// Thu, Sep 9, 2021, 7:28 AM
<span >
  <span class="weekday">Thu</span>
  <span class="literal">, </span>
  <span class="month">Sep</span>
  <span class="literal"> </span>
  <span class="day">9</span>
  <span class="literal">, </span>
  <span class="year">2021</span>
  <span class="literal">, </span>
  <span class="hour">7</span>
  <span class="literal">:</span>
  <span class="minute">21</span>
  <span class="literal"> </span>
  <span class="dayPeriod">AM</span>
</span>

参考资料


今天的分享就到这边,如果大家对我分享的内容有兴趣欢迎点击追踪 & 订阅系列文章,如果对内容有任何疑问,或是文章内容有错误,都非常欢迎留言讨论或指教的!

明天要来分享的是新的主题 Storybook,那我们明天见!


<<:  DAY10 - 如何挑选自学的教材

>>:  Day 7 - Maximum Subarray

[Day 14] Audit perfomance — 模型也要期末稽核༼ಢ_ಢ༽

It is only our conception of time that makes us c...

RDS备份还原与地端的差异

在使用面板成功备份还原後, 再使用SSMS实作的可行性, 是否跟地端的一样? 先使用UI方式备份, ...

Leetcode 挑战 Day 11 [242. Valid Anagram]

242. Valid Anagram 今天我们一起挑战leetcode第242题Valid Anag...

[D25] placeholder

写在前面 test for placeholder test for placeholder tes...

Day29:歪楼无极限(全英文笔记 - III)

虽然今天已经是最後一天,但如果明天系统仍然可以发文的话,会先继续发文,方便之後回顾整理系列文时,能够...