Julia 日期和时间

Dates 模块提供了两种关于时间的数据类型: Date 和 DateTime, 精度分别为天和毫秒, 都是抽象数据类型 TimeType 的子类型.

 使用两种数据类型的原因很简单: 某些操作本身很简单, 无论是从代码上看还是逻辑上, 使用高精度的数据类型是完全没有必要的. 例如, Date 只精确到天 (也就是说, 没有小时, 分钟或者秒), 所以使用时就不需要考虑时区, 夏令时和闰秒.

Date 和 DateTime 都不过是 Int64 的简单封装, 仅有的一个成员变量 instant 实际上的类型是 UTInstant{P}, 代表的是基于世界时的机器时间 [1]. Datetime 类型是 不考虑时区 的 (根据 Python 的讲法), 或者说是 Java 8 里面的 本地时间.

  额外的时间日期操作可以通过 Timezones.jl 扩展包来获取, 其中的数据来自 Olsen Time Zone Database . 

Date 和 DateTime 遵循 ISO 8601 标准. 值得注意的一点是, ISO 8601 关于公元前日期的处理比较特殊. 简单来说, 公元前的最后一天是公元前 1-12-31, 接下来第二天是公元 1-1-1, 所以是没有公元 0 年存在的. 而 ISO 标准认定, 公元前 1 年是 0 年, 所以 0000-12-21 是 0001-01-01 的前一天, -0001 是公元前 2 年, -0003 是公元前 3 年, 等等.

[1] 一般来说有两种常用的时间表示法, 一种是基于地球的自转状态 (地球转一整圈 = 1 天), 另一种基于 SI 秒 (固定的常量). 

这两种表示方法是不一样的. 试想一下, 因为地球自转, 基于世界时的的秒可能是不等长的. 但总得来说, 基于世界时的 Date 和 DateTime 是一种简化的方案, 例如闰秒的情况不需要考虑. 这种表示时间的方案的正式名称为世界时

这意味着, 每一分钟有 60 秒, 每一天有 60 小时, 这样使得关于时间的计算更自然, 简单.

构造函数

Date 和 DateType 可以通过整数或者 Period 构造, 通过直接传入, 或者作为与特定时间的差值:

julia> DateTime(2013)
  2013-01-01T00:00:00

  julia> DateTime(2013,7)
  2013-07-01T00:00:00

  julia> DateTime(2013,7,1)
  2013-07-01T00:00:00

  julia> DateTime(2013,7,1,12)
  2013-07-01T12:00:00

  julia> DateTime(2013,7,1,12,30)
  2013-07-01T12:30:00

  julia> DateTime(2013,7,1,12,30,59)
  2013-07-01T12:30:59

  julia> DateTime(2013,7,1,12,30,59,1)
  2013-07-01T12:30:59.001

  julia> Date(2013)
  2013-01-01

  julia> Date(2013,7)
  2013-07-01

  julia> Date(2013,7,1)
  2013-07-01

  julia> Date(Dates.Year(2013),Dates.Month(7),Dates.Day(1))
  2013-07-01

  julia> Date(Dates.Month(7),Dates.Year(2013))
  2013-07-01

Date 和 DateTime 解析是通过格式化的字符串实现的. 格式化的字符串是指 分隔 的或者 固定宽度 的 "字符段" 来表示一段时间, 然后传递给 Date 或者 DateTime 的构造函数.

使用分隔的字符段方法, 需要显示指明分隔符, 所以 "y-m-d" 告诉解析器第一个和第二个字符段中间有一个 -, 例如 "2014-07-16"ym 和 d 字符告诉解析器每个字符段的含义.

固定宽度字符段是使用固定宽度的字符串来表示时间. 所以 "yyyymmdd" 相对应的时间字符串为 "20140716".

同时字符表示的月份也可以被解析, 通过使用 u 和 U, 分别是月份的简称和全称. 默认支持英文的月份名称, 所以 u 对应于 JanFebMar 等等, U 对应于 JanuaryFebruaryMarch 等等. 然而, 同 dayname 和 monthname 一样, 本地化的输出也可以实现, 通过向 Dates.MONTHTOVALUEABBR 和 Dates.MONTHTOVALUE 字典添加 locale=>Dict{UTF8String, Int} 类型的映射.

更多的解析和格式化的例子可以参考 tests/dates/io.jl .

时间间隔/比较

计算两个 Date 或者 DateTime 之间的间隔是很直观的, 考虑到他们不过是 UTInstant{Day} 和 UTInstant{Millisecond} 的简单封装. 不同点是, 计算两个 Date 的时间间隔, 返回的是 Day, 而计算DateTime 时间间隔返回的是 Millisecond. 同样的, 比较两个 TimeType 本质上是比较两个 Int64

julia> dt = Date(2012,2,29)
  2012-02-29

  julia> dt2 = Date(2000,2,1)
  2000-02-01

  julia> dump(dt)
  Date
    instant: UTInstant{Day}
      periods: Day
        value: Int64 734562

  julia> dump(dt2)
  Date
  instant: UTInstant{Day}
    periods: Day
      value: Int64 730151

  julia> dt > dt2
  true

  julia> dt != dt2
  true

  julia> dt + dt2
  Operation not defined for TimeTypes

  julia> dt * dt2
  Operation not defined for TimeTypes

  julia> dt / dt2
  Operation not defined for TimeTypes

  julia> dt - dt2
  4411 days

  julia> dt2 - dt
  -4411 days

  julia> dt = DateTime(2012,2,29)
  2012-02-29T00:00:00

  julia> dt2 = DateTime(2000,2,1)
  2000-02-01T00:00:00

  julia> dt - dt2
  381110402000 milliseconds

访问函数

因为 Date 和 DateTime 类型是使用 Int64 的封装, 具体的某一部分可以通过访问函数来获得. 小写字母的获取函数返回值为整数:

julia> t = Date(2014,1,31)
  2014-01-31

  julia> Dates.year(t)
  2014

  julia> Dates.month(t)
  1

  julia> Dates.week(t)
  5

  julia> Dates.day(t)
  31
大写字母的获取函数返回值为 Period :

julia> Dates.Year(t)
  2014 years

  julia> Dates.Day(t)
  31 days
查询函数

查询函数可以用来获得关于 TimeType 的额外信息, 例如某个日期是星期几:

julia> t = Date(2014,1,31)
  2014-01-31

  julia> Dates.dayofweek(t)
  5

  julia> Dates.dayname(t)
  "Friday"

  julia> Dates.dayofweekofmonth(t)
  5  # 5th Friday of January
月份信息 :

julia> Dates.monthname(t)
  "January"

  julia> Dates.daysinmonth(t)
  31
年份信息和季节信息 :

julia> Dates.isleapyear(t)
  false

  julia> Dates.dayofyear(t)
  31

  julia> Dates.quarterofyear(t)
  1

  julia> Dates.dayofquarter(t)
  31

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2022

备案号:京ICP备15003423号-3