Java是如何实现的;“一年一周”;真的有用吗?

Java是如何实现的;“一年一周”;真的有用吗?,java,simpledateformat,Java,Simpledateformat,这是一个简单的错误:我在SimpleDateFormat对象的格式字符串中使用了YYYY而不是YYYY。但是我完全被错误格式字符串的测试结果所迷惑 此代码: @Test public void whatTheHell() { try { SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/YYYY"); Date d1 = sdf.parse("01/07/2016

这是一个简单的错误:我在
SimpleDateFormat
对象的格式字符串中使用了
YYYY
而不是
YYYY
。但是我完全被错误格式字符串的测试结果所迷惑

此代码:

@Test
public void whatTheHell() {
        try {
                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/YYYY");

                Date d1 = sdf.parse("01/07/2016");
                Date d2 = sdf.parse("02/08/2016");
                Date d3 = sdf.parse("11/29/2027");

                System.out.println(d1.toString());
                System.out.println(d2.toString());
                System.out.println(d3.toString());
        } catch (ParseException pe) {
                fail("ParseException: " + pe.getMessage());
        }
}
生成此输出:

Sun Dec 27 00:00:00 PST 2015
Sun Dec 27 00:00:00 PST 2015
Sun Dec 27 00:00:00 PST 2026
我已经在这里阅读了关于“Y”参数的文档:,但是我仍然看不到在这里工作的逻辑。特别是最后一个例子:我有点理解如何将1月(可能是2月)的日期转换为前一年的12月,但将11月29日的日期向后移动11个月让我感到困惑。12月27日有什么特别的

有人能解释一下吗

更多信息

@Jan建议依赖toString()方法可能会有问题,因此我定义了一种日期格式,用与上面相同的代码打印
YYYY-MM-dd'-'YYYY-MM-dd
。以下是附加输出:

2016 12 27 - 2015 12 27
2016 12 27 - 2015 12 27
2027 12 27 - 2026 12 27

很简单:2015年12月27日是2016年第1周的第1天(2026年12月27日是2027年第1周的第1天)。这可以通过添加以下行进行验证:

SimpleDateFormat odf = new SimpleDateFormat("YYYY-ww-u");
System.out.println(odf.format(d1));
System.out.println(odf.format(d2));
System.out.println(odf.format(d3));
如果一个
SimpleDataFormat
输出一个日期,它可以使用所有字段:年、月、日、周、月周、年中周、周年等

解析时,
SimpleDataFormat
需要一组匹配的值:天、月、年周中日、年中周、周年。由于您提供了一周一年,但没有提供一周中的某一天和一年中的某一周,因此这些值被假定为1


实际值取决于您的区域设置:

  • 一年中的哪一周是第一周
  • 哪一天是一周的第一天
(见附件)

在我的系统上(使用de-ch locale,格式为“EEE-MMM-dd-HH:mm:ss-zzz-yyyy-yyy-ww-u”),我得到

墨西哥人2016年1月4日00:00:00墨西哥湾-2016-01-1 墨西哥人2016年1月4日00:00:00墨西哥湾-2016-01-1 Mo Jan 04 00:00:00 MEZ 2027-2027-01-1定义各不相同 一周可以用不同的方式定义。例如,在美国,一周的第一天通常被认为是星期天,而在欧洲和许多其他地方,第一天是星期一

同样,基于周的年份中的周也可以用不同的方式定义

  • 第一周包括1月1日
  • 周#1是包含一周中特定日期(如周日)的第一周
  • 第一周是仅包含新年天数的第一周,没有上一年的日期
  • ……还有更多
您正在使用的旧类隐式使用由
区域设置指定的定义。应用的区域设置也是隐式的,如果不另行指定,则使用JVM当前的默认
区域设置

有关定义一周的难度的更多有趣细节,请参见此问题

ISO 8601 有一个实用的日期时间处理国际标准

最重要的是:

  • 星期一开始
  • 第一周是日历年的第一个星期四
  • 一年由52或53个整周组成
  • 一年可以有上一个日历年的一天或多天,也可以有下一个日历年的一天或多天
我建议尽可能使用ISO8601标准定义。该标准定义简单且符合逻辑,各行业越来越多地采用该定义

java.time time类为类中基于周的年提供了一些支持

看这个

ld.toString():2019-01-01

周:1

org.threeten.extra.YearWeek
但是如果要做很多这方面的工作,我建议将库添加到您的项目中。你会发现这门课很有帮助。该类提供了几种简便的方法,例如为该周内的任何一天生成
LocalDate

LocalDate ld = LocalDate.of ( 2019 , Month.JANUARY , 1 );
YearWeek yw = YearWeek.from ( ld );
LocalDate startOfWeek = yw.atDay ( DayOfWeek.MONDAY );
ld.toString():2019-01-01

yw.toString():2019-W01

startOfWeek.toString():2018-12-31

请注意,2019年以周为基础的年份中的第一天是上一个日历年2018年的日期,而不是2019年的日期


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

该项目现已启动,建议迁移到类

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • 、和更高版本-标准Java API的一部分,带有捆绑实现
  • Java9添加了一些次要功能和修复
  • 大多数java.time功能都在中向后移植到Java6和Java7
  • 更高版本的Android捆绑包实现了java.time类

  • 对于早期的Android(依赖于toString()要呈现有用的内容也是乐观的。您可能希望对输出使用不同的DateFormat。例如,包括yyyy和yyyy的DateFormat?有关年与周的说明,请参阅year@theo谢谢,但这只解释了日期在一年中的第一周或最后一周时的变化,这可能只是我三次考试中的第一次mples.@Jan:好主意,但是使用格式字符串为
    yyyyyy
    的格式会得到一致的结果:#1和#2都给出
    2016 2015
    和#3给出
    2027 2026
    。这并不能让我们得到任何结果。但是输出的日期格式确认日期为12月27日吗?否则正确,但“和2027年的星期”这肯定是错误的。修正答案的这一部分。2015年与2027年相对应毫无意义。不完全正确:在所有这些情况下,
    u
    的输出
    LocalDate ld = LocalDate.of( 2019 , Month.JANUARY , 1 ) ;
    long week = ld.get( WeekFields.ISO.weekOfWeekBasedYear() ) ;
    
    LocalDate ld = LocalDate.of ( 2019 , Month.JANUARY , 1 );
    YearWeek yw = YearWeek.from ( ld );
    LocalDate startOfWeek = yw.atDay ( DayOfWeek.MONDAY );