搜索
首页Javajava教程YYYY? yyyy!

YYYY? yyyy!

Nov 17, 2024 pm 02:51 PM

你知道 Java 日期模式中的 'Y' 和 'y' 字符有什么区别吗?在本文中,我们将探讨不正确的日期格式如何导致错误。我们还将推出新的 Java V6122 诊断规则,让您免于突然的时间旅行。

YYYY? yyyy!

介绍

掸去大TODO笔记本上的灰尘后,我们偶然发现了一个特别有趣的案例。该文章的评论者强调了潜在的问题。

评论
顺便说一句,这里有一个主意:Java 中的 SimpleDateFormat 可以带来新年惊喜——用小写字母书写的年份与用大写字母书写的年份不同。在这一年的最后一周,您可能会突然发现自己身处未来,因为 2021 年 12 月 27 日至 2021 年 12 月 31 日的“YYYY”是 2022 年,而不是某些人预期的 2021 年。

让我们来一探究竟。

问题分析

日期格式

如果您忘记了 SimpleDateFormat 是什么,您可以在这里温习一下知识。

为了存储和显示日期,我们经常需要它们遵循特定的模式。 SimpleDateFormat 是一个类,使我们能够根据给定的模式轻松格式化日期。除了格式化之外,SimpleDateFormat还可以解析字符串并将其转换为日期对象。

这就是 Java 所能提供的全部吗?除了 SimpleDateFormat 之外,DateTimeFormatter 类还可以格式化日期。

让我向您展示使用这两个类的示例。

如果我们通过 SimpleDateFormat 格式化日期:

public static void main(String[] args) {
    Date date = new Date("2024/12/31");
    var dateFormatter = new SimpleDateFormat("dd-MM-yyyy");
    System.out.println(dateFormatter.format(date));
}

控制台显示以下内容:

2024年12月31日

这里发生了什么?

我们有日期,我们想以特定格式保存/显示它。为了实现它,我们通过将模式字符串传递给构造函数来创建 SimpleDateFormat 对象。日期的格式完全按照此模式进行。 format 方法返回格式化日期的字符串表示形式。这正是我们想要的。

这里是同样的事情,但是我们使用DateTimeFormatter:

public static void main(String[] args) {
    LocalDate date = LocalDate.of(2024, 12, 31);
    var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
    System.out.println(formatter.format(date));
}

控制台显示以下内容:

2024年12月31日

相同的步骤和结果,但略有不同:DateTimeFormatter 使我们能够仅格式化由实现 TemporalAccessor 接口的类表示的日期。例如,其中包括 LocalDateLocalDateTimeSimpleDateFormat 仅格式化 Date 类的对象。

让我们回到评论。在日期模式中使用“Y”代替“y”真的会改变结果吗?

看一下代码:

public static void main(String[] args) {
    Date date = new Date("2024/12/31");
    var dateFormatter = new SimpleDateFormat("dd-MM-yyyy");
    System.out.println(dateFormatter.format(date));
}

控制台显示以下内容:

2025年12月31日

哎呀。 DateTimeFormatter 也是一样吗?

代码如下:

public static void main(String[] args) {
    LocalDate date = LocalDate.of(2024, 12, 31);
    var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
    System.out.println(formatter.format(date));
}

控制台显示以下内容:

2025年12月31日

我们确实旅行到了一年后的未来。是时候看看发生了什么了。

问题本质

我的第一步是查看 SimpleDateFormat 类的文档。下面是表格的一小部分,描述了日期模式如何解释我们感兴趣的字母字符:

Letter Date or Time Component Presentation Examples
y Year Year 1996; 96
Y Week year Year 2009; 09

一年一周?让我解释一下。

周年是基于一年中的周数的一年。它是什么意思以及为什么它很重要?

在某些任务中,一年中周的序号很重要。为了确定一周的序列号,我们需要决定首先考虑哪一周。这是因为从一年到另一年的过渡通常会导致两年之间有几周的时间。那么,我们如何判断本周属于哪一年呢? ISO-8601 标准对此进行了规定。

根据这个标准,一年中的第一周必须满足以下条件:

  • 一周的第一天是星期一;
  • 一年中每周最少有四天。

由此,我们可以推导出一个简单的规则:如果星期四是一月,则一周被认为是一年的第一周。

一个现实生活中的例子可以进一步阐明这一点。

让我们从示例中获取日期,即 31.12.2024。以下是包含我们日期的一周的日历片段(2024 年 12 月至 2025 年 1 月):

Mo Tu We Th Fr Sa Su
30 31 1 2 3 4 5

本周被视为 2025 年的第一周,因为它满足上述条件(一月有 5 天)。因此,如果我们使用“Y”说明符,我们就会得到 2025 年。

你可以猜到,DateTimeFormatter 的情况是完全一样的。

需要注意的是,我们不仅可以穿越到未来,还可以穿越到过去。

我们换个日期吧,2027 年 1 月 1 日。

2027 年的第一周包括 1 月 1 日吗?再次,让我们查阅日历。

以下是包含我们日期的一周的日历片段(2026 年 12 月 - 2027 年 1 月):

Mo Tu We Th Fr Sa Su
28 29 30 31 1 2 3

由于这一周只有 3 天(根据要求第一周应该是 4 天),因此算作 2026 年的最后一周。所以,日期使用“Y”格式化时角色,将向我们展示2026。

这是证据。看一下代码:

public static void main(String[] args) {
    Date date = new Date("2024/12/31");
    var dateFormatter = new SimpleDateFormat("dd-MM-yyyy");
    System.out.println(dateFormatter.format(date));
}

控制台显示以下内容:

2026 年 1 月 1 日

好的,我们已经剖析了这个问题。我们还发现向 PVS-Studio Java 分析器添加专用诊断规则非常有趣。

实际项目中的错误

诊断规则已经写好了,是时候测试一下了。

在分析器的开发过程中,测试阶段之一涉及运行回归测试。我们有一篇关于此过程的文章。简而言之,当我们添加新的诊断规则时,我们会分析大量开源项目,并将新报告与参考报告进行比较。

在此诊断规则的情况下,分析器针对多个项目发出了新的警告。让我们来看看它们。

充气城堡

在这个项目中,诊断规则指向的代码片段是相同的,所以我只展示其中一个。

看一下代码:

public static void main(String[] args) {
    LocalDate date = LocalDate.of(2024, 12, 31);
    var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
    System.out.println(formatter.format(date));
}

PVS-Studio 警告:

V6122 检测到使用“Y”(周年)模式:它可能打算使用“y”(年)。 SkeinParameters.java 246

首先,我浏览了GitHub。如果这确实是一个错误,开发人员已经发现它并提交了修复怎么办?这正是发生的事情。这是提交的链接,你可以查看一下。模式中的所有“Y”(周年)字符均替换为“y”(年)。

您可能想知道为什么提交是在相对较长的时间之前进行的。让我解释一下。我们的回归测试并不是为了持续控制这个或那个开源项目的质量。任务是查看添加新诊断规则时报告如何变化:旧警告不应消失,不应出现新错误,因为这表明分析仪存在问题。所以,检查的代码必须是相同的。

开放格罗克

现在让我们看一下触发诊断规则的第二个项目。

PVS-Studio 警告:

V6122 检测到使用“Y”(周年)模式:它可能打算使用“y”(年)。 RepositoryInfo.java 77

代码:

public static void main(String[] args) {
    Date date = new Date("2024/12/31");
    var dateFormatter = new SimpleDateFormat("dd-MM-YYYY");
    System.out.println(dateFormatter.format(date));
}

就像之前的项目一样,我冲到提交处看看发生了什么。首先,值得注意的是,由于重构,该字段已移至其派生类 Repository(这里是提交的链接)。我进一步搜索并找到了包含修复程序的提交。日期模式中的“Y”字符已替换为“y”:

public static void main(String[] args) {
    LocalDate date = LocalDate.of(2024, 12, 31);
    var formatter = DateTimeFormatter.ofPattern("dd-MM-YYYY");
    System.out.println(formatter.format(date));
}

所以,这里也是一个错误。

结论

在PVS-Studio,我们欢迎来自社区的任何反馈。在解决 Habr 用户的评论后,我们通过添加一些有用的诊断规则来增强 Java 分析器。因此,如果您有任何想法想与我们分享,我们很乐意在本文的评论部分与您聊天。

顺便说一句,诊断规则已在 10 月 7.33 版本中引入。因此,如果您想尝试我们的分析器,请使用此链接。

仅此而已。让我们把事情总结到这里吧。希望突然的前进(或倒退)一年不会让您措手不及。

以上是YYYY? yyyy!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何将Maven或Gradle用于高级Java项目管理,构建自动化和依赖性解决方案?如何将Maven或Gradle用于高级Java项目管理,构建自动化和依赖性解决方案?Mar 17, 2025 pm 05:46 PM

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

如何使用适当的版本控制和依赖项管理创建和使用自定义Java库(JAR文件)?如何使用适当的版本控制和依赖项管理创建和使用自定义Java库(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

如何使用咖啡因或Guava Cache等库在Java应用程序中实现多层缓存?如何使用咖啡因或Guava Cache等库在Java应用程序中实现多层缓存?Mar 17, 2025 pm 05:44 PM

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

如何将JPA(Java持久性API)用于具有高级功能(例如缓存和懒惰加载)的对象相关映射?如何将JPA(Java持久性API)用于具有高级功能(例如缓存和懒惰加载)的对象相关映射?Mar 17, 2025 pm 05:43 PM

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类负载机制如何起作用,包括不同的类载荷及其委托模型?Java的类负载机制如何起作用,包括不同的类载荷及其委托模型?Mar 17, 2025 pm 05:35 PM

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)