SDL3_API分类参考_日期时间(CategoryTime)

2026-3-6 / 0 评论 / 8 阅读

日期时间子系统(CategoryTime)

SDL 提供实时时钟和日期/时间相关的函数,用于处理日历时间(区别于 Timer 模块的短时长计时)。

本模块核心使用两种数据类型:

  • SDL_Time:表示从某个特定时间点("纪元/epoch")开始的纳秒数(时间戳);
  • SDL_DateTime:将时间拆解为人类可读的组件(年、月、日、时、分、秒等)。

模块的大部分功能围绕这两种类型的相互转换,以及获取时间相关的辅助信息展开。


函数

  • SDL_DateTimeToTime:将 SDL_DateTime 结构体转换为 SDL_Time 时间戳(纳秒级)
  • SDL_GetCurrentTime:获取当前系统时间的 SDL_Time 时间戳(基于 UTC 时间,纳秒级)
  • SDL_GetDateTimeLocalePreferences:获取当前系统的日期/时间格式偏好(如日期格式、时间格式)
  • SDL_GetDayOfWeek:根据 SDL_DateTime 计算该日期是一周中的第几天(0=周日,1=周一,…,6=周六)
  • SDL_GetDayOfYear:根据 SDL_DateTime 计算该日期是一年中的第几天(1-366)
  • SDL_GetDaysInMonth:获取指定年份和月份的天数(自动处理闰年)
  • SDL_TimeFromWindows:将 Windows 系统的 FILETIME 时间转换为 SDL_Time 时间戳
  • SDL_TimeToDateTime:将 SDL_Time 时间戳转换为 SDL_DateTime 结构体(拆解为年月日时分秒)
  • SDL_TimeToWindows:将 SDL_Time 时间戳转换为 Windows 系统的 FILETIME 时间格式

数据类型

  • (无)

结构体

  • SDL_DateTime:日期时间结构体(包含年、月、日、时、分、秒、毫秒、微秒、纳秒、时区偏移等字段)

枚举

  • SDL_DateFormat:日期格式枚举(如 MM/DD/YYYY、DD/MM/YYYY、YYYY/MM/DD 等)
  • SDL_TimeFormat:时间格式枚举(如 12小时制、24小时制)

FreeBASIC 示例代码

' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"

' 补充 SDL_Time 类型定义(纳秒级时间戳,无符号64位整型)
Type SDL_Time As ULLong

' 补充 SDL_DateTime 结构体定义
Type SDL_DateTime
    year As Integer          ' 年份(如 2026)
    month As Integer         ' 月份(1-12)
    day As Integer           ' 日期(1-31)
    hour As Integer          ' 小时(0-23)
    minute As Integer        ' 分钟(0-59)
    second As Integer        ' 秒(0-59)
    millisecond As Integer   ' 毫秒(0-999)
    microsecond As Integer   ' 微秒(0-999)
    nanosecond As Integer    ' 纳秒(0-999)
    tz_offset_minutes As Integer ' 时区偏移(分钟,UTC+8 为 480)
End Type

' 补充日期/时间格式枚举定义
Enum SDL_DateFormat
    SDL_DATE_FORMAT_MMDDYYYY = 0  ' 月/日/年(美式)
    SDL_DATE_FORMAT_DDMMYYYY = 1  ' 日/月/年(欧式)
    SDL_DATE_FORMAT_YYYYMMDD = 2  ' 年/月/日(ISO)
End Enum

Enum SDL_TimeFormat
    SDL_TIME_FORMAT_24HR = 0      ' 24小时制
    SDL_TIME_FORMAT_12HR = 1      ' 12小时制
End Enum

' 补充函数声明(FreeBASIC 绑定可能缺失)
Declare Function SDL_GetCurrentTime CDecl () As SDL_Time
Declare Function SDL_TimeToDateTime CDecl (ByVal time As SDL_Time, ByVal dt As SDL_DateTime Ptr) As Integer
Declare Function SDL_DateTimeToTime CDecl (ByVal dt As SDL_DateTime Ptr, ByVal time As SDL_Time Ptr) As Integer
Declare Function SDL_GetDayOfWeek CDecl (ByVal dt As SDL_DateTime Ptr) As Integer
Declare Function SDL_GetDayOfYear CDecl (ByVal dt As SDL_DateTime Ptr) As Integer
Declare Function SDL_GetDaysInMonth CDecl (ByVal year As Integer, ByVal month As Integer) As Integer
Declare Sub SDL_GetDateTimeLocalePreferences CDecl (ByVal date_format As SDL_DateFormat Ptr, ByVal time_format As SDL_TimeFormat Ptr)

' 打印 SDL_DateTime 结构体内容
Sub PrintDateTime(ByVal dt As SDL_DateTime Ptr, ByVal title As ZString Ptr)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "=== %s ===", title)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  日期:%04d年%02d月%02d日", dt->year, dt->month, dt->day)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  时间:%02d:%02d:%02d.%03d%03d%03d", dt->hour, dt->minute, dt->second, _
                dt->millisecond, dt->microsecond, dt->nanosecond)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  时区:UTC%+d (偏移 %d 分钟)", dt->tz_offset_minutes / 60, dt->tz_offset_minutes)

    ' 计算星期几
    Dim As Integer weekday = SDL_GetDayOfWeek(dt)
    Dim As ZString * 10 weekdayStr
    Select Case weekday
        Case 0: weekdayStr = "周日"
        Case 1: weekdayStr = "周一"
        Case 2: weekdayStr = "周二"
        Case 3: weekdayStr = "周三"
        Case 4: weekdayStr = "周四"
        Case 5: weekdayStr = "周五"
        Case 6: weekdayStr = "周六"
    End Select
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  星期:%s (一周的第%d天)", weekdayStr, weekday)

    ' 计算一年中的第几天
    Dim As Integer dayOfYear = SDL_GetDayOfYear(dt)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  年内天数:第%d天", dayOfYear)

    ' 计算当月天数
    Dim As Integer daysInMonth = SDL_GetDaysInMonth(dt->year, dt->month)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  当月天数:%d天", daysInMonth)
End Sub

' 主程序
Sub Main()
    ' 初始化 SDL(Time 模块无需显式初始化子系统)
    If (SDL_Init(0) < 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
        Exit Sub
    End If

    ' ========== 1. 获取当前系统时间 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【1. 获取当前系统时间】")
    Dim As SDL_Time currentTime = SDL_GetCurrentTime()
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "当前时间戳(纳秒):%llu", currentTime)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "当前时间戳(秒):%.3f", currentTime / 1000000000.0)

    ' ========== 2. 时间戳转换为日期时间 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【2. 时间戳转日期时间】")
    Dim As SDL_DateTime dt
    If (SDL_TimeToDateTime(currentTime, @dt) = 0) Then
        PrintDateTime(@dt, "当前系统日期时间")
    Else
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "时间戳转日期时间失败:%s", SDL_GetError())
    End If

    ' ========== 3. 日期时间转换为时间戳 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【3. 日期时间转时间戳】")
    ' 手动构造一个日期时间(2026年3月8日 12:34:56.123456789,UTC+8)
    Dim As SDL_DateTime customDt
    customDt.year = 2026
    customDt.month = 3
    customDt.day = 8
    customDt.hour = 12
    customDt.minute = 34
    customDt.second = 56
    customDt.millisecond = 123
    customDt.microsecond = 456
    customDt.nanosecond = 789
    customDt.tz_offset_minutes = 8 * 60 ' UTC+8

    PrintDateTime(@customDt, "自定义日期时间")

    ' 转换为时间戳
    Dim As SDL_Time customTime
    If (SDL_DateTimeToTime(@customDt, @customTime) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "自定义日期时间对应的时间戳:")
        SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  纳秒:%llu", customTime)
        SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "  秒:%.9f", customTime / 1000000000.0)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "日期时间转时间戳失败:%s", SDL_GetError())
    End If

    ' ========== 4. 获取系统日期时间格式偏好 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【4. 获取系统日期时间格式偏好】")
    Dim As SDL_DateFormat dateFmt
    Dim As SDL_TimeFormat timeFmt
    SDL_GetDateTimeLocalePreferences(@dateFmt, @timeFmt)

    Dim As ZString * 20 dateFmtStr
    Select Case dateFmt
        Case SDL_DATE_FORMAT_MMDDYYYY: dateFmtStr = "MM/DD/YYYY(月/日/年)"
        Case SDL_DATE_FORMAT_DDMMYYYY: dateFmtStr = "DD/MM/YYYY(日/月/年)"
        Case SDL_DATE_FORMAT_YYYYMMDD: dateFmtStr = "YYYY/MM/DD(年/月/日)"
    End Select

    Dim As ZString * 20 timeFmtStr
    Select Case timeFmt
        Case SDL_TIME_FORMAT_24HR: timeFmtStr = "24小时制"
        Case SDL_TIME_FORMAT_12HR: timeFmtStr = "12小时制"
    End Select

    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统日期格式:%s", dateFmtStr)
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统时间格式:%s", timeFmtStr)

    ' ========== 5. 闰年测试 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【5. 闰年/月份天数测试】")
    Dim As Integer years(0 To 3) = {2024, 2025, 2026, 2000}
    Dim As Integer months(0 To 1) = {2, 4} ' 2月、4月

    For i As Integer = 0 To 3
        For j As Integer = 0 To 1
            Dim As Integer days = SDL_GetDaysInMonth(years(i), months(j))
            Dim As ZString * 10 leapStr = IIf(months(j)=2 And days=29, "(闰年)", "")
            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%d年%d月的天数:%d天 %s", years(i), months(j), days, leapStr)
        Next
    Next

    ' 清理 SDL
    SDL_Quit()

    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出")
End Sub

' 运行主程序
Main()

核心知识点补充

  1. SDL_Time 核心特性

    • 本质是无符号64位整型(ULLong),表示从 "Unix 纪元"(1970-01-01 00:00:00 UTC)开始的纳秒数;
    • 范围覆盖约 584 年(0 ~ 18446744073709551615 纳秒),足够满足常规日期时间需求;
    • 与系统时钟同步,可精准表示当前系统时间。
  2. SDL_DateTime 字段规则

    • 月份范围:1(1月)~ 12(12月),而非0开始;
    • 日期范围:1 ~ 当月最大天数(由 SDL_GetDaysInMonth 计算);
    • 时间字段:小时(0-23)、分钟(0-59)、秒(0-59),毫秒/微秒/纳秒均为 0-999;
    • 时区偏移:以分钟为单位,UTC+8 对应 480 分钟,UTC-5 对应 -300 分钟。
  3. 闰年判断逻辑

    • SDL_GetDaysInMonth 会自动处理闰年:
      • 能被400整除的年份是闰年;
      • 能被4整除但不能被100整除的年份是闰年;
      • 其他年份为平年;
    • 闰年2月有29天,平年2月有28天。
  4. 本地化格式偏好

    • SDL_GetDateTimeLocalePreferences 获取系统默认的日期/时间显示格式;
    • 常见日期格式:
      • MM/DD/YYYY:美式(如 03/08/2026);
      • DD/MM/YYYY:欧式(如 08/03/2026);
      • YYYY/MM/DD:ISO标准(如 2026/03/08);
    • 时间格式:12小时制(带AM/PM)、24小时制。

总结

  1. 核心优势

    • 提供跨平台的日历时间处理接口,屏蔽不同系统的时间API差异;
    • 支持纳秒级高精度时间戳,兼顾精度与易用性;
    • 内置日期时间拆解/组装、星期/年内天数计算、闰年判断等实用功能;
    • 支持本地化格式偏好获取,适配不同地区的显示习惯。
  2. 使用建议

    • SDL_GetCurrentTime 是获取当前时间的首选方式(UTC 时间,无时区偏差);
    • 转换时间戳/日期时间时,需检查函数返回值(0=成功,非0=失败);
    • 处理时区时,注意 tz_offset_minutes 字段的单位是分钟,需转换为小时展示;
    • 计算星期/年内天数前,确保 SDL_DateTime 结构体的年月日字段有效。
  3. 关键接口

    • 时间获取:SDL_GetCurrentTime()
    • 类型转换:SDL_TimeToDateTime()/SDL_DateTimeToTime()
    • 日期计算:SDL_GetDayOfWeek()/SDL_GetDayOfYear()/SDL_GetDaysInMonth()
    • 本地化:SDL_GetDateTimeLocalePreferences()

评论一下?

OωO
取消