如何使用Ramda解决小时格式?
How to use Ramda to solve hour format?
我是函数式编程的新手,在学习了函数式编程和 Ramda 的基础知识后,我决定亲自动手,替换之前使用命令式编程编写的一些函数。我决定重写函数来执行一个简单的任务
转换13:22 to 1:22 PM
这是我想了很多之后写的代码
const formatHr = (R.cond([
[R.lt(R.__,13), R.identity],
[R.gte(R.__,13), R.subtract(R.__,12)],
]));
const updateHr = x => {
const hr = parseInt(R.head(x));
const newHr = formatHr(hr);
const newX = R.update(0, newHr, x);
const meridiem = R.ifElse(R.lt(R.__,12),x => R.identity('AM'), x => R.identity('PM'))(hr);
return `${R.join(':',newX)} ${meridiem}`
}
const getHour = R.pipe(R.split(':'), updateHr);
const hr = getHour('13:22'); // 1:22 PM
对于可以使用 ES6 语法用 vanilla javascript 轻松编写的内容来说,这似乎太复杂了。谁能告诉我如何高效地完成它?
虽然我们肯定可以使用 Ramda 工具对此进行改进,但似乎没有理由这样做。我认为你的目标有点误入歧途。 Ramda(免责声明:我是它的作者之一)旨在为您提供帮助您以某种方式编码的工具。它不是一种新的 JS 方言,您应该将所有代码转换成它。
我会这样写这个函数:
const formatHour = (time) => {
const [h, m] = time .split (':')
return `${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`
}
console .log (formatHour ('13:22'))
当我想确保我正在编写功能代码时,我检查的要点是我正在编写的内容是否不涉及数据突变(通常包括不重新分配变量,尽管有时我会为了性能而这样做原因)并且我只有纯函数——那些总是 return 相同输入的相同输出并且没有副作用的函数。这个函数通过了这两个测试。我们不改变任何东西,我们只分配 h
和 m
一次,没有重新分配。该函数仅依赖于它的参数来计算一致的结果,而不会影响任何外部的东西。
在编写函数式代码时,我更喜欢其他一些功能,但这些功能不太重要,而且可能更具争议性。我不喜欢有很多中间变量,如果它们只使用一次,我经常将它们内联。因此我更喜欢上面的版本而不是这个:
const formatHour = (time) => {
const [hour, minute] = time .split (':')
const newHour = hour > 12 ? hour - 12 : hour
const meridian = hour >= 12 ? 'PM' : 'AM'
return `${newHour}:${minute} ${meridian}`
}
但这是一个次要的偏好,如果我的代码在没有辅助局部变量的情况下开始变得不可读,我通常会选择其他方式。另一个,虽然,我尽量经常做:我更喜欢使用纯表达式而不是语句。我将在 if
语句上使用条件语句(三元组)。我将选择单表达式主体以在 {
-}
分隔的块上使用箭头函数。
这会诱使我以这种方式编写此函数:
const formatHour = (time, [h, m] = time .split (':')) =>
`${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`;
而且我经常做这样的事情。但是像这样使用默认参数也会让人头疼。使用该函数的早期版本,我可以写
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
//=> ["7:04 AM", "11:59 AM", "12:01 PM", "1:22 PM"]
但这在最新版本中不起作用。 Array.prototype.map
提供当前项目之外的两个附加参数:它的索引和整个数组。所以在最后一个版本中,如果我们将它传递给 map
,[h, m]
参数的格式不正确,因为该位置有一个整数索引而不是数组。我们会得到某种解构错误。我们可以选择通过添加几个未使用的参数来解决这个问题,像这样:
const formatHour = (time, _, __, [h, m] = time .split (':')) =>
`${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`;
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
//=> ["7:04 AM", "11:59 AM", "12:01 PM", "1:22 PM"]
但这似乎很笨拙。我有时会这样做,尤其是对于内部功能。但是当你不知道你的函数将如何在野外使用时,这是一个风险。
据我所知,Ramda 在这方面没有提供任何改进。
但是,如果我尝试用 Ramda 函数来做这件事,我可能会和你做的有点不同。
首先,Ramda 的 cond
when you are only dealing with a single case, ifElse
有一些更简单的替代品。但即便如此,当其中之一
您的分支机构只是 return 数据完好无损。然后你可以使用 when
(or its counterpart, unless
) 在满足条件时转换数据,否则就不用管它。
其次,我可能会使用 evolve
函数来更改数据结构的一部分(具有 hour
和 minute
属性的数组)但保留另一部分(s) 一个人。
最后,因为我必须在两个地方使用小时并将它们的结果合并为一个,所以我会使用 converge
or, even better when possible, lift
来管理它。
const formatHour = pipe (
split (':'),
lift (([h, m], meridian) => `${h}:${m} ${meridian}`) (
evolve ([when (gt (__, 12), subtract (__, 12))]),
([h, m]) => h >= 12 ? 'PM' : 'AM'
)
);
console .log (
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, split, lift, evolve, when, gt, __, subtract} = R </script>
请注意,我不想让这完全没有意义。我可以通过替换
([h, m]) => h >= 12 ? 'PM' : 'AM'
和
ifElse(pipe(head, gte(__, 12)), always('PM'), always('AM'))
而且我相信我们可以为
做一些更丑陋的事情
([h, m], meridian) => `${h}:${m} ${meridian}`
但我看不出有任何意义。我们正在 降低 此处的可读性,如果我们尝试另一个,情况会变得更糟。
这就是重点。 Ramda 是一个工具。当它改进代码中的某些重要内容时使用它:可读性、可维护性、性能或其他有形的东西。但是不要仅仅因为它可用并且已经包含在您的项目中就使用它。目标永远不应该是“我如何使用 Ramda 完成这项工作?”,除非你正在努力学习 Ramda。目标应该包括简单性、可维护性、性能等。如果 Ramda 帮助您实现这些目标,那就太好了。没有的时候跳过它。
迟到的想法
我刚刚意识到上面的 none 正确处理了午夜时间。假设您希望 "00:35"
变为 "12:35 AM"
,这需要对上述所有版本进行细微调整。第一个会变成
const formatHour = (time) => {
const [h, m] = time .split (':')
return `${h > 12 ? h - 12 : h == 0 ? 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`
}
并且需要将类似的更改应用到其他更改。
拆分后我会使用R.applySpec,因为每个映射函数都可以访问所有原始值。
我不会将 Ramda 用于映射函数(normalizeHour
和 amPm
),因为解构和文字模板更易于使用且可读性也更好。
格式化值后,使用 R.props 获取它们(R.values 也可以,但不太明确),然后连接值。
const { pipe, split, applySpec, props, join } = R
const normalizeHour = ([m]) => m > 12 ? m - 12 : m
const amPm = ([h, m]) => `${m} ${h >= 12 && h < 24 ? 'PM' : 'AM'}`
const formatHour = pipe(
split(':'),
applySpec({
h: normalizeHour,
m: amPm,
}),
props(['h', 'm']),
join(' ')
);
console.log(
['7:04', '11:59', '12:01', '13:22', '24:53'].map(formatHour)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
午夜 00:00 和 24:00
In the 24-hour time notation, the day begins at midnight, 00:00, and the last minute of the day begins at 23:59. Where convenient, the notation 24:00 may also be used to refer to midnight at the end of a given date[5] — that is, 24:00 of one day is the same time as 00:00 of the following day.
The notation 24:00 mainly serves to refer to the exact end of a day in a time interval. A typical usage is giving opening hours ending at midnight (e.g. "00:00–24:00", "07:00–24:00"). Similarly, some bus and train timetables show 00:00 as departure time and 24:00 as arrival time. Legal contracts often run from the start date at 00:00 until the end date at 24:00.
While the 24-hour notation unambiguously distinguishes between midnight at the start (00:00) and end (24:00) of any given date, there is no commonly accepted distinction among users of the 12-hour notation. Style guides and military communication regulations in some English-speaking countries discourage the use of 24:00 even in the 24-hour notation, and recommend reporting times near midnight as 23:59 or 00:01 instead.[6] Sometimes the use of 00:00 is also avoided.[6] In variance with this, the correspondence manual for the United States Navy and United States Marine Corps formerly specified 0001 to 2400.[7] The manual was updated in June 2015 to use 0000 to 2359
次后 24:00
Time-of-day notations beyond 24:00 (such as 24:01 or 25:00 instead of 00:01 or 01:00) are not commonly used and not covered by the relevant standards. However, they have been used occasionally in some special contexts in the United Kingdom, France, Spain, Canada, Japan, South Korea, Hong Kong and China where business hours extend beyond midnight, such as broadcast television production and scheduling.
(引用:https://en.wikipedia.org/wiki/24-hour_clock)
我们的节目
此处的其他答案讨论了我们在选择以不同方式表达我们的程序时所做的一些权衡。在这个答案中,我特别想专注于实现一个适应上述变化的健壮的格式化程序。我们将编写 format24
,它需要一个 24 小时时间字符串和一个格式化函数,并期望它像这样工作 -
format24("00:00", to12) //=> "12:00 AM"
format24("11:59", to12) //=> "11:59 AM"
format24("12:01", to12) //=> "12:01 PM"
format24("13:22", to12) //=> "1:22 PM"
format24("24:00", to12) //=> "12:00 AM"
format24("25:01", to12) //=> "1:01 AM"
本例中的格式化函数 to12
接受 0-23 hour
和 0-59 minute
-
const to12 = (h = 0, m = 0) =>
`${formatHour(h % 12)}:${formatMinute(m)} ${formatMeridian(h)}`
const formatHour = (h = 0) =>
h === 0 ? "12" : String(h)
const formatMinute = (m = 0) =>
m < 10 ? `0${m}` : String(m)
const formatMeridian = (h = 0) =>
h < 12 ? "AM" : "PM"
最后,我们实现format24
-
const format24 = (time = "00:00", formatter = String) =>
{ const [ _, h = 0, m = 0 ] =
time.match(/^(\d?\d):(\d\d)/) || []
const minutes =
Number(h) * 60 + Number(m)
return formatter
( Math.floor(minutes / 60) % 24 // 0-23
, minutes % 60 // 0-59
)
}
验证它是否正常工作
const times =
[ "00:00", "00:01", "01:23", "11:59", "12:00", "12:01", "13:22", "23:59", "24:00", "24:01", "25:00", "27:45" ]
times.forEach(t => console.log(t, "->", format24(t, to12)))
输入 -> 输出
00:00 -> 12:00 AM
00:01 -> 12:01 AM
01:23 -> 1:23 AM
11:59 -> 11:59 AM
12:00 -> 12:00 PM
12:01 -> 12:01 PM
13:22 -> 1:22 PM
23:59 -> 11:59 PM
24:00 -> 12:00 AM
24:01 -> 12:01 AM
25:00 -> 1:00 AM
27:45 -> 3:45 AM
代码演示
展开下面的代码片段以在您自己的浏览器中验证 format24
的结果 -
const format24 = (time = "00:00", formatter = String) =>
{ const [ _, h = 0, m = 0 ] =
time.match(/^(\d?\d):(\d\d)/) || []
const minutes =
Number(h) * 60 + Number(m)
return formatter
( Math.floor(minutes / 60) % 24
, minutes % 60
)
}
const to12 = (h = 0, m = 0) =>
`${formatHour(h % 12)}:${formatMinute(m)} ${formatMeridian(h)}`
const formatHour = (h = 0) =>
h === 0 ? "12" : String(h)
const formatMinute = (m = 0) =>
m < 10 ? `0${m}` : String(m)
const formatMeridian = (h = 0) =>
h < 12 ? "AM" : "PM"
const times =
[ "00:00", "00:01", "01:23", "11:59", "12:00", "12:01", "13:22", "23:59", "24:00", "24:01", "25:00", "27:45" ]
times.forEach(t => console.log(t, "->", format24(t, to12)))
无效次数
如果时间格式完全错误,我们可能应该 throw
一个错误让调用者知道输入时间无法可靠地转换 -
const format24 = (time = "00:00", formatter = String) =>
{ const [ match, h = 0, m = 0 ] =
time.match(/^(\d\d):(\d\d)$/) || []
if (match === undefined)
throw Error("invalid 24-hour time")
// ...
}
format24("foo", to12) // Error: invalid 24-hour time
format24("1:23", to12) // Error: invalid 24-hour time
format24("123:456", to12) // Error: invalid 24-hour time
我是函数式编程的新手,在学习了函数式编程和 Ramda 的基础知识后,我决定亲自动手,替换之前使用命令式编程编写的一些函数。我决定重写函数来执行一个简单的任务
转换13:22 to 1:22 PM
这是我想了很多之后写的代码
const formatHr = (R.cond([
[R.lt(R.__,13), R.identity],
[R.gte(R.__,13), R.subtract(R.__,12)],
]));
const updateHr = x => {
const hr = parseInt(R.head(x));
const newHr = formatHr(hr);
const newX = R.update(0, newHr, x);
const meridiem = R.ifElse(R.lt(R.__,12),x => R.identity('AM'), x => R.identity('PM'))(hr);
return `${R.join(':',newX)} ${meridiem}`
}
const getHour = R.pipe(R.split(':'), updateHr);
const hr = getHour('13:22'); // 1:22 PM
对于可以使用 ES6 语法用 vanilla javascript 轻松编写的内容来说,这似乎太复杂了。谁能告诉我如何高效地完成它?
虽然我们肯定可以使用 Ramda 工具对此进行改进,但似乎没有理由这样做。我认为你的目标有点误入歧途。 Ramda(免责声明:我是它的作者之一)旨在为您提供帮助您以某种方式编码的工具。它不是一种新的 JS 方言,您应该将所有代码转换成它。
我会这样写这个函数:
const formatHour = (time) => {
const [h, m] = time .split (':')
return `${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`
}
console .log (formatHour ('13:22'))
当我想确保我正在编写功能代码时,我检查的要点是我正在编写的内容是否不涉及数据突变(通常包括不重新分配变量,尽管有时我会为了性能而这样做原因)并且我只有纯函数——那些总是 return 相同输入的相同输出并且没有副作用的函数。这个函数通过了这两个测试。我们不改变任何东西,我们只分配 h
和 m
一次,没有重新分配。该函数仅依赖于它的参数来计算一致的结果,而不会影响任何外部的东西。
在编写函数式代码时,我更喜欢其他一些功能,但这些功能不太重要,而且可能更具争议性。我不喜欢有很多中间变量,如果它们只使用一次,我经常将它们内联。因此我更喜欢上面的版本而不是这个:
const formatHour = (time) => {
const [hour, minute] = time .split (':')
const newHour = hour > 12 ? hour - 12 : hour
const meridian = hour >= 12 ? 'PM' : 'AM'
return `${newHour}:${minute} ${meridian}`
}
但这是一个次要的偏好,如果我的代码在没有辅助局部变量的情况下开始变得不可读,我通常会选择其他方式。另一个,虽然,我尽量经常做:我更喜欢使用纯表达式而不是语句。我将在 if
语句上使用条件语句(三元组)。我将选择单表达式主体以在 {
-}
分隔的块上使用箭头函数。
这会诱使我以这种方式编写此函数:
const formatHour = (time, [h, m] = time .split (':')) =>
`${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`;
而且我经常做这样的事情。但是像这样使用默认参数也会让人头疼。使用该函数的早期版本,我可以写
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
//=> ["7:04 AM", "11:59 AM", "12:01 PM", "1:22 PM"]
但这在最新版本中不起作用。 Array.prototype.map
提供当前项目之外的两个附加参数:它的索引和整个数组。所以在最后一个版本中,如果我们将它传递给 map
,[h, m]
参数的格式不正确,因为该位置有一个整数索引而不是数组。我们会得到某种解构错误。我们可以选择通过添加几个未使用的参数来解决这个问题,像这样:
const formatHour = (time, _, __, [h, m] = time .split (':')) =>
`${h > 12 ? h - 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`;
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
//=> ["7:04 AM", "11:59 AM", "12:01 PM", "1:22 PM"]
但这似乎很笨拙。我有时会这样做,尤其是对于内部功能。但是当你不知道你的函数将如何在野外使用时,这是一个风险。
据我所知,Ramda 在这方面没有提供任何改进。
但是,如果我尝试用 Ramda 函数来做这件事,我可能会和你做的有点不同。
首先,Ramda 的 cond
when you are only dealing with a single case, ifElse
有一些更简单的替代品。但即便如此,当其中之一
您的分支机构只是 return 数据完好无损。然后你可以使用 when
(or its counterpart, unless
) 在满足条件时转换数据,否则就不用管它。
其次,我可能会使用 evolve
函数来更改数据结构的一部分(具有 hour
和 minute
属性的数组)但保留另一部分(s) 一个人。
最后,因为我必须在两个地方使用小时并将它们的结果合并为一个,所以我会使用 converge
or, even better when possible, lift
来管理它。
const formatHour = pipe (
split (':'),
lift (([h, m], meridian) => `${h}:${m} ${meridian}`) (
evolve ([when (gt (__, 12), subtract (__, 12))]),
([h, m]) => h >= 12 ? 'PM' : 'AM'
)
);
console .log (
['7:04', '11:59', '12:01', '13:22'] .map (formatHour)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, split, lift, evolve, when, gt, __, subtract} = R </script>
请注意,我不想让这完全没有意义。我可以通过替换
([h, m]) => h >= 12 ? 'PM' : 'AM'
和
ifElse(pipe(head, gte(__, 12)), always('PM'), always('AM'))
而且我相信我们可以为
做一些更丑陋的事情 ([h, m], meridian) => `${h}:${m} ${meridian}`
但我看不出有任何意义。我们正在 降低 此处的可读性,如果我们尝试另一个,情况会变得更糟。
这就是重点。 Ramda 是一个工具。当它改进代码中的某些重要内容时使用它:可读性、可维护性、性能或其他有形的东西。但是不要仅仅因为它可用并且已经包含在您的项目中就使用它。目标永远不应该是“我如何使用 Ramda 完成这项工作?”,除非你正在努力学习 Ramda。目标应该包括简单性、可维护性、性能等。如果 Ramda 帮助您实现这些目标,那就太好了。没有的时候跳过它。
迟到的想法
我刚刚意识到上面的 none 正确处理了午夜时间。假设您希望 "00:35"
变为 "12:35 AM"
,这需要对上述所有版本进行细微调整。第一个会变成
const formatHour = (time) => {
const [h, m] = time .split (':')
return `${h > 12 ? h - 12 : h == 0 ? 12 : h}:${m} ${h >= 12 ? 'PM' : 'AM'}`
}
并且需要将类似的更改应用到其他更改。
拆分后我会使用R.applySpec,因为每个映射函数都可以访问所有原始值。
我不会将 Ramda 用于映射函数(normalizeHour
和 amPm
),因为解构和文字模板更易于使用且可读性也更好。
格式化值后,使用 R.props 获取它们(R.values 也可以,但不太明确),然后连接值。
const { pipe, split, applySpec, props, join } = R
const normalizeHour = ([m]) => m > 12 ? m - 12 : m
const amPm = ([h, m]) => `${m} ${h >= 12 && h < 24 ? 'PM' : 'AM'}`
const formatHour = pipe(
split(':'),
applySpec({
h: normalizeHour,
m: amPm,
}),
props(['h', 'm']),
join(' ')
);
console.log(
['7:04', '11:59', '12:01', '13:22', '24:53'].map(formatHour)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
午夜 00:00 和 24:00
In the 24-hour time notation, the day begins at midnight, 00:00, and the last minute of the day begins at 23:59. Where convenient, the notation 24:00 may also be used to refer to midnight at the end of a given date[5] — that is, 24:00 of one day is the same time as 00:00 of the following day.
The notation 24:00 mainly serves to refer to the exact end of a day in a time interval. A typical usage is giving opening hours ending at midnight (e.g. "00:00–24:00", "07:00–24:00"). Similarly, some bus and train timetables show 00:00 as departure time and 24:00 as arrival time. Legal contracts often run from the start date at 00:00 until the end date at 24:00.
While the 24-hour notation unambiguously distinguishes between midnight at the start (00:00) and end (24:00) of any given date, there is no commonly accepted distinction among users of the 12-hour notation. Style guides and military communication regulations in some English-speaking countries discourage the use of 24:00 even in the 24-hour notation, and recommend reporting times near midnight as 23:59 or 00:01 instead.[6] Sometimes the use of 00:00 is also avoided.[6] In variance with this, the correspondence manual for the United States Navy and United States Marine Corps formerly specified 0001 to 2400.[7] The manual was updated in June 2015 to use 0000 to 2359
次后 24:00
Time-of-day notations beyond 24:00 (such as 24:01 or 25:00 instead of 00:01 or 01:00) are not commonly used and not covered by the relevant standards. However, they have been used occasionally in some special contexts in the United Kingdom, France, Spain, Canada, Japan, South Korea, Hong Kong and China where business hours extend beyond midnight, such as broadcast television production and scheduling.
(引用:https://en.wikipedia.org/wiki/24-hour_clock)
我们的节目
此处的其他答案讨论了我们在选择以不同方式表达我们的程序时所做的一些权衡。在这个答案中,我特别想专注于实现一个适应上述变化的健壮的格式化程序。我们将编写 format24
,它需要一个 24 小时时间字符串和一个格式化函数,并期望它像这样工作 -
format24("00:00", to12) //=> "12:00 AM"
format24("11:59", to12) //=> "11:59 AM"
format24("12:01", to12) //=> "12:01 PM"
format24("13:22", to12) //=> "1:22 PM"
format24("24:00", to12) //=> "12:00 AM"
format24("25:01", to12) //=> "1:01 AM"
本例中的格式化函数 to12
接受 0-23 hour
和 0-59 minute
-
const to12 = (h = 0, m = 0) =>
`${formatHour(h % 12)}:${formatMinute(m)} ${formatMeridian(h)}`
const formatHour = (h = 0) =>
h === 0 ? "12" : String(h)
const formatMinute = (m = 0) =>
m < 10 ? `0${m}` : String(m)
const formatMeridian = (h = 0) =>
h < 12 ? "AM" : "PM"
最后,我们实现format24
-
const format24 = (time = "00:00", formatter = String) =>
{ const [ _, h = 0, m = 0 ] =
time.match(/^(\d?\d):(\d\d)/) || []
const minutes =
Number(h) * 60 + Number(m)
return formatter
( Math.floor(minutes / 60) % 24 // 0-23
, minutes % 60 // 0-59
)
}
验证它是否正常工作
const times =
[ "00:00", "00:01", "01:23", "11:59", "12:00", "12:01", "13:22", "23:59", "24:00", "24:01", "25:00", "27:45" ]
times.forEach(t => console.log(t, "->", format24(t, to12)))
输入 -> 输出
00:00 -> 12:00 AM
00:01 -> 12:01 AM
01:23 -> 1:23 AM
11:59 -> 11:59 AM
12:00 -> 12:00 PM
12:01 -> 12:01 PM
13:22 -> 1:22 PM
23:59 -> 11:59 PM
24:00 -> 12:00 AM
24:01 -> 12:01 AM
25:00 -> 1:00 AM
27:45 -> 3:45 AM
代码演示
展开下面的代码片段以在您自己的浏览器中验证 format24
的结果 -
const format24 = (time = "00:00", formatter = String) =>
{ const [ _, h = 0, m = 0 ] =
time.match(/^(\d?\d):(\d\d)/) || []
const minutes =
Number(h) * 60 + Number(m)
return formatter
( Math.floor(minutes / 60) % 24
, minutes % 60
)
}
const to12 = (h = 0, m = 0) =>
`${formatHour(h % 12)}:${formatMinute(m)} ${formatMeridian(h)}`
const formatHour = (h = 0) =>
h === 0 ? "12" : String(h)
const formatMinute = (m = 0) =>
m < 10 ? `0${m}` : String(m)
const formatMeridian = (h = 0) =>
h < 12 ? "AM" : "PM"
const times =
[ "00:00", "00:01", "01:23", "11:59", "12:00", "12:01", "13:22", "23:59", "24:00", "24:01", "25:00", "27:45" ]
times.forEach(t => console.log(t, "->", format24(t, to12)))
无效次数
如果时间格式完全错误,我们可能应该 throw
一个错误让调用者知道输入时间无法可靠地转换 -
const format24 = (time = "00:00", formatter = String) =>
{ const [ match, h = 0, m = 0 ] =
time.match(/^(\d\d):(\d\d)$/) || []
if (match === undefined)
throw Error("invalid 24-hour time")
// ...
}
format24("foo", to12) // Error: invalid 24-hour time
format24("1:23", to12) // Error: invalid 24-hour time
format24("123:456", to12) // Error: invalid 24-hour time