日期和时间管理

对于如何在 Gambas 中正确使用 Date 数据类型 ,所有用户(不仅仅是新手)都存在很多困惑。 此页面将尝试弄清它。

日期不是字符串

混乱主要来自这样一个事实:您正在通过使用区域设置字符串表示形式来考虑日期,就好像日期数据类型代表区域设置日期一样。在这里就错了!

内部表达方式

在内部,Gambas 使用两个 32 位整数存储日期值:

  • 第一个整数是自起点以来的天数,起点为过去的特定时刻。这是 日期 部分。一天应该正好是 86,400 秒,这是一个近似值。

  • 第二个整数是与该天数相加的毫秒数。这是 时间 部分。

换句话说,Gambas 日期/时间 值是一个完完全全的时间戳。 绝对时间的概念是一种实用的计算选择。

Gambas 在内部如何存储其日期数据类型并不重要

您必须清楚地记住重要的事情: Gambas Dates不是通常意义上的日期,而是瞬间,即~时间点~。

但是Gambas中没有办法直接写一个Date常量。您始终必须使用 Date 构建日期的函数或使用 CStr, CDate, Str$Val 转换字符串表示的日期形式。

因此,每次您操作日期表达式时,Gambas 都必须决定您的日期表示是 U.T.C.时间还是本地时间。换句话说,与日期表示关联的时区是隐式的。

这有点像字符串字符集的问题:字符串的字符集是隐式的。它不与字符串一起存储。

Gambas 函数假设日期表示为:

  • 在 U.T.C.中,使用美式日期格式

  • 在本地时中,时区由 System.TimeZone 属性指定,该时区直接来自当前系统配置。日期格式为本地日期格式。

时区取决于系统中的配置和你将日期转换为字符串时的实际时间(时区可能会在一年中发生变化,或者由于突然的政治决定而变化)。日期格式取决于 System.Language 属性指定的当前语言。

自从 3.18

从Gambas 3.18,时区可以在日期字符串表示中明确指定。

语法为:

<Old date string representation> <space> [ UTC | GMT ] [ + | - ] HH [ :MM ]

以下是与日期相关的函数列表,以及它们是否涉及U.T.C.或当地时间。

处理 U.T.C. 和美式日期格式的函数

CDate 将表达式转换为日期和时间值。
CStr 将日期和时间值转换为字符串。

解释器在进行隐式数据类型转换时使用这些函数。

处理当地时间的函数

Date 返回不包含时间成分的日期,或从其成分中创建一个本地时间的日期和时间值。
DateAdd 加一段时间到给定日期。
DateDiff 返回两个日期之间的间隔。
Day 返回Date值的日期
Hour 返回Date值的小时
Minute 返回Date值的分钟
Month 返回Date值的月份
Second 返回Date值的秒
Str$ 将日期和时间值转换为字符串。
Time 返回Date值的时间部分,或从其组件创建时间值。
Val 将字符串转换为日期和时间值,条件是该字符串以本地日期和时间格式表示。
Week 返回Date值的周数。
WeekDay 返回Date值的星期几。
Year 返回Date值的年份。

隐式转换

当心日期和字符串之间的隐式转换!

  • PRINT 使用 Str$ 方法打印日期。所以日期是以当地时间打印的。

  • 所有其他隐式转换使用 CStrCDate 函数,假定使用的是 UTC 时间。

CStrCDate 是互逆操作. 意味着
CStr(CDate(SomeString)) = SomeString
and
CDate(CStr(SomeDate)) = SomeDate
永远为真。

日期是数字

日期和时间值隐式转换为浮点数,其整数部分是内部日期部分(自起点以来的天数),小数部分是内部时间部分。

因此,您可以使用标准 +- 运算符轻松地在日期之间进行日算术运算。

目前,起始时刻是 UTC 时间的午夜。

因此,如果您的时区不为空, CFloat(Date(Now)) 则不会返回整数!

空日期和仅时间日期

仅时间日期是日期和时间值,其中仅日期部分为零。在这种特殊情况下,不考虑时区。当您想要对时间进行算术运算时,这非常有用。

空日期是日期和时间部分均为零的日期和时间值。它们相当于常数NULL。使用空日期进行算术会引发错误。

日期存储

以可靠的方式存储日期的唯一方法是使用 UTC 表示形式。切勿用本地时间表示形式存储日期!或者至少始终使用相同的时区。

将日期存储在二进制文件中

您必须使用 WRITEREAD 指令与 As Date 语法一起使用。 这样您就可以将日期值的 UTC 内部表示直接写入文件中。

请注意,内部表示可能会发生变化,因此您通常不应假设二进制值将来具有相同的含义。

但如果内部表示发生变化,READ 和 WRITE 将被修改为向后兼容,因此您最终可以假设 READ 读取出的二进制值将保持不变。

在文本文件中存储日期

您必须使用 CStrCDate 函数写入和读取日期值的 UTC 字符串表示形式。 您也可以使用 CFloat 日期值,将内部日期时间戳存储为浮点值。它也可以工作,但可读性较差。 否则,您可以使用任何自定义表示(例如 Unix 时间戳),前提是它是相对 UTC 绝对时间的恒定偏移。

日期和日历

对于仅日期表示的具体问题,请参阅 日期和日历.