在 MicroPython 中解析 ISO 日期时间以获取工作日

Parsing an ISO datetime in MicroPython to get weekday

提问人:John Horner 提问时间:10/20/2023 最后编辑:tripleeeJohn Horner 更新时间:10/20/2023 访问量:66

问:

没有办法在 MicroPython 中解析 ISO 日期时间对象?我的Raspberry Pi Pico调用了一个REST API,其中包含ISO 8601格式的日期项。

{"title":"Green","date":"2023-10-18T00:00:00"}

但 MicroPython 似乎只有一个时间函数,而不是一个日期时间函数,而且时间函数似乎无法解析字符串。

例如,我基本上需要将 ISO 字符串转换为“Wednesday 18”。

python datetime 解析 micropython iso8601

评论

0赞 FObersteiner 10/20/2023
看起来 CPython 时间模块到 Micropython 的移植不包含 strptime/strftime 功能 - 我可以想象为什么您不想在微控制器上拥有所有这些功能。为什么要更改输入的格式;这里的背景是什么?
0赞 Tim Roberts 10/20/2023
幸运的是,如果您知道自己有一个 ISO 8601 字符串,那么自己解析它就很容易了。
0赞 AKX 10/20/2023
您可以仅使用字符串切片和强制转换来解析 ISO 8601 时间戳。int()
0赞 John Horner 10/20/2023
我目前正在手动解析它,是 Python 的新手,不习惯 MicroPython 的准系统。我需要从日期中删除“Monday”或“October”,并假设C# DateTime.ToString(“ddd MMMM”)等价。

答:

2赞 Dan Nagle 10/20/2023 #1

有一种算法可以确定给定日期的星期几,该算法适用于可追溯到 1753 年的日期。

sample = {"title":"Green","date":"2023-10-18T00:00:00"}

def day_string_from_iso8601_date(date_str):
    month_keys = (1,4,4,0,2,5,0,3,6,1,4,6)
    days_of_week = ("Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
    [yyyy, mm, dd] = [int(i) for i in date_str.split('T')[0].split('-')]
    leap_year_modifier = 0
    if ((yyyy % 400 == 0) or (yyyy % 100 != 0) and (yyyy % 4 == 0)) and mm in (1, 2):
        leap_year_modifier = -1
    a = yyyy % 100
    b = a // 4
    year_modifier = 0
    if yyyy < 1800:
        year_modifier = 4
    elif 1799 < yyyy < 1900:
        year_modifier = 2
    elif 1999 < yyyy < 2100:
        year_modifier = -1
    day = (a + b + dd + month_keys[mm-1] + leap_year_modifier + year_modifier) % 7
    return f"{days_of_week[day]} {dd}"


day_string_from_iso8601_date(sample["date"])

输出:

'Wednesday 18'

编辑:有一种更简单的方法可以使用 Python 或 Micropython 中的模块来解决此问题。2000年1月1日,正好是星期六。这条信息以及要分析的日期的天数可用于计算工作日。timeutime

Python 的函数将一个包含 9 个元素的元组作为参数,并返回自 epoch(1970 年 1 月 1 日)以来经过的秒数。time.mktime()struct_time

import time

# January 1 2000 as dummy time struct
jan_1_2000 = (2000, 1, 1, 1, 0, 0, 0, 0, 0)
seconds_in_a_day = 24 * 60 * 60 # 86400
days_since_epoch = time.mktime(jan_1_2000) // seconds_in_a_day # 10957.0

2000年1月1日星期六是1970年1月1日星期四之后的第10,957天。和常量可用于在微处理器上节省一点计算能力。8640010957

import utime

def day_string_from_iso8601(date_str):
    days_of_week = ("Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday")
    [yyyy, mm, dd] = [int(i) for i in date_str.split('T')[0].split('-')]
    the_date = (yyyy, mm, dd, 1, 0, 0, 0, 0, 0)
    day = int((utime.mktime(the_date) // 86400) - 10957) % 7
    return f"{days_of_week[day]} {dd}"

评论

0赞 John Horner 10/20/2023
完善。我希望能够像在 C# 中一样解析为日期时间并格式化日期字符串以获取工作日名称和月份名称。我通过使用 12 字符串数组手动将 ISO 解析为 INT 来获得月份名称,但这是数周的最后一部分。
0赞 Dan Nagle 10/20/2023
我用一个不太复杂的解决方案更新了答案。