尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

在 Elixir 中正确比较 DateTime 结构体:用 DateTime.compare/2 取代结构比较

在 Elixir 中正确比较 DateTime 结构体:用 DateTime.compare/2 取代结构比较 文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载导读在 Elixir 中DateTime是以结构体struct形式存在的复合值直接用/2、/2、/2等运算符比较两个日期时间得到的往往不是“时间先后”的语义而是“结构字段是否相同”的结果。本文以 elixir/comparing-datetime-structs.md 为核心讲解为何要使用DateTime.compare/2进行准确的日期时间比较并给出可直接复制运行的示例代码、返回值语义以及结合本仓库其他笔记总结出的/判断实战模式。读完本文你将掌握 Elixir 标准库中比较日期时间点的正确姿势。为什么/2、/2、/2不能用于 DateTime 比较Elixir 的文档在解释DateTime时特别强调了一条原则在 Elixir 中使用/2、/2、/2等运算符进行比较时比较是结构性的structural基于DateTime结构体的字段进行。也就是说当你写下older newer时Elixir 并不是在问“这两个时间点是否相同”而是在问“这两个结构体的全部字段是否逐字段相等”。DateTime结构体内部包含了year、month、day、hour、minute、second、microsecond、time_zone、zone_abbr、utc_offset、std_offset等一组字段。任何一个字段不同哪怕只是微秒精度差异或时区缩写表示不同结构比较的结果都会是false。这种“结构相等”语义在普通映射map比较时很直观但在日期时间这种表示同一个时间点可能有多种等价写法的值上就会带来误导两个表示完全相同的瞬间、但携带不同时区信息如Etc/UTC与Asia/Shanghai的DateTime结构上并不相等两个数值上不同一前一后的时间点结构比较只会告诉你“不相等”却无法告诉你谁早谁晚。因此如果要做“时间先后、大小关系”这类语义比较就必须绕过结构比较使用DateTime模块专门提供的compare/2函数。使用DateTime.compare/2进行准确比较DateTime.compare/2接收两个DateTime结构体返回一个原子atom直接表达两个时间点之间的先后关系。原笔记给出了完整的示例{:ok, older} DateTime.from_naive(~N[2016-05-24 13:26:08.003], Etc/UTC) {:ok, newer} DateTime.from_naive(~N[2017-11-24 13:26:08.003], Etc/UTC) DateTime.compare(older, newer) # :lt DateTime.compare(newer, older) # :gt DateTime.compare(newer, newer) # :eq返回值共有三种含义如下表所示返回值含义对应关系:ltless than第一个参数表示的时间点早于第二个参数:gtgreater than第一个参数表示的时间点晚于第二个参数:eqequal两个参数表示同一个时间点通过这个返回值可以非常清晰地映射到小于、大于、等于三种关系进而在case、cond或后续逻辑中做出分支处理。示例代码中的两个关键构造这段示例代码还顺带展示了构造日期时间的两个惯用法值得单独说明~N[...]是 NaiveDateTime 字面量 sigil~N[2016-05-24 13:26:08.003]直接构造一个不含时区信息的NaiveDateTime值包含微秒部分.003。DateTime.from_naive/2为 NaiveDateTime 附加时区DateTime.from_naive(~N[...], Etc/UTC)返回{:ok, datetime}将不带时区的朴素日期时间与指定时区这里是Etc/UTC结合升级为真正的DateTime结构体。这也是从源码层面印证DateTime必须携带时区信息、而NaiveDateTime不携带时区信息的体现。如果两个值本身就是DateTime例如从DateTime.utc_now/0或数据库返回的结果则可以直接传入DateTime.compare/2无需再经过from_naive/2。实战模式结合in操作符判断与在实际业务中我们经常需要判断“某个时间是否早于或等于当前时间”也就是/这类带等号的关系。DateTime.compare/2只返回三种原子正好可以与本仓库 elixir/check-list-membership.md 中介绍的in操作符组合使用。in操作符用于判断某个值是否出现在列表中。于是判断“datetime早于或等于当前时刻”即可以写作{:ok, datetime} DateTime.from_naive(~N[2016-05-24 13:26:08.003], Etc/UTC) DateTime.compare(datetime, DateTime.utc_now()) in [:lt, :eq]这段表达式的含义是compare/2的结果要么是:lt更早要么是:eq相同只要命中两者之一就等价于datetime DateTime.utc_now()。同理如果需要判断“严格晚于当前时刻”可以借助not操作符取反DateTime.compare(datetime, DateTime.utc_now()) not in [:lt, :eq]即“结果既不是:lt也不是:eq”等价于datetime DateTime.utc_now()。这种“比较结果原子 成员判断”的组合是 Elixir 社区处理日期时间范围判断的常见写法可读性与可维护性都优于依赖结构比较的表达式。相关的时间处理基础笔记围绕日期时间的构造与处理本仓库的 Elixir 分类下还有几篇可以相互印证的笔记elixir/create-a-date-with-the-date-sigil.md介绍 Elixir 1.3 引入的~D[...]日期 sigil用于直接构造Date结构体~D[2016-01-01]并可访问.year、.month、.day等字段。elixir/do-you-have-the-time.md 与 elixir/do-you-have-the-time-part-2.md演示了获取并处理时间的两种方式——早期通过 Erlang 的:erlang.time/0元组拆解Elixir 1.3 之后则可以用Time模块如Time.from_erl!/1、Time.to_string/1完成。这些笔记与本篇共同构成了一套 Elixir 日期时间Date、Time、NaiveDateTime、DateTime从构造、格式化到比较的完整学习路径。小结在 Elixir 中比较两个日期时间需要记住以下要点不要用/2、/2、/2直接比较DateTime它们执行的是基于结构体字段的结构比较无法正确表达时间点的大小关系。使用DateTime.compare/2它返回:lt、:gt、:eq三种原子分别表示“早于”“晚于”“等于”。结合in与not in操作符可以方便地表达、等带等号的范围判断这在判断“截止时间”“过期判断”等业务场景中非常实用。完整的可运行示例与原始笔记位于 elixir/comparing-datetime-structs.md与之配套的成员判断技巧见 elixir/check-list-membership.md。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐探索Z-Image-Turbo-bf16的文本编码器Qwen3-4B如何精准理解复杂绘画指令探索Z Image Turbo bf16的文本编码器Qwen3 4B如何精准理解复杂绘画指令 在当今AI图像生成领域Z Image Turbo bf16凭借AlphaFold结构比较RMSD计算与结构相似性分析AlphaFold结构比较RMSD计算与结构相似性分析 引言蛋白质结构比较的核心挑战 在计算生物学领域准确评估蛋白质结构预测结果的质量是至关重要的。研究人人工智能深度学习生物信息学科学计算科研Difftastic 结构化 Diff 入门让差异比较真正理解代码语法Difftastic 结构化 Diff 入门让差异比较真正理解代码语法 Difftastic 是一款依据文件 语法 进行比较的结构化structurald开发工具CLI上一篇免费增强WeMod体验的终极指南Wand-Enhancer完全使用教程下一篇Wand-Enhancer完整指南3步免费解锁Wand专业版功能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表