在 jq 输出中将 12h 时间值格式化为 24h

Format 12h time values to 24h in jq output

我的 json 中有从 jq 获得的 "h:mm AM"/"h:mm PM" 格式的值。 有没有办法解析这些 12h 格式的值并将它们转换为 24h 格式的值?

示例输入:

{ "times": [ [ "8:16 AM", "EventA" ], [ "3:19 PM", "EventB" ] ]}

期望的输出:

{ "times": [ [ "8:16", "EventA" ], [ "15:19", "EventB" ] ]}

以下内容比此处实际需要的更通用:

def to24h:
    (capture("(?<pre>.*)(?<h>[01][0-9])(?<m>:[0-5][0-9]) *(?<midi>[aApP])[mM](?<post>.*)") //
     capture("(?<pre>.*)(?<h>[0-9])(?<m>:[0-5][0-9]) *(?<midi>[aApP])[mM](?<post>.*)"))

  | (.midi|ascii_upcase) as $midi
  | .pre + (if $midi == "A" then .h else "\(12+(.h|tonumber))" end) + .m + .post ;

有了这个定义,您可以使用过滤器转换给定的输入:

.times |= map( map(to24h // .) )

或者如果您希望检查所有字符串:

walk( if type=="string" then to24h // . else . end)

我们可以使用 jq 的日期函数吗?

jq '(.times[] | .[])
    |= ( if test("^\d{1,2}:\d{1,2} [AP]M$"; "i")
         then ( strptime("%H:%M %p") | strftime("%k:%M") | sub("^ "; "") )
         else . end ) '

每次使用 strptimestrftime 进行解析和重新格式化。

% jq -c '.times[][0] |= (strptime("%H:%M %p") | strftime("%H:%M"))'
{ "times": [ [ "8:16 AM", "EventA" ], [ "3:19 PM", "EventB" ] ]}
{"times":[["08:16","EventA"],["15:19","EventB"]]}
^C

strptime 生成一个列表,其中 %H 匹配的小时根据 %p 匹配的修饰符调整为 24 小时制时间; strftime 然后简单地输出任何时间。

困难的部分不是转换;它确定应将转换应用于 的值。在这里,我们假设每次都是 times 键的数组值中数组的第一个元素。