将日期转换为 GregorianCalendar 日期格式

converting date to GregorianCalendar Date format

我想将 org.joda.time.LocalDate 对象转换为 java.util.GregorianCalendar。 java.util.GregorianCalendar 从索引 0 到 11 显示的月份。因此,十月用数字 9 表示,十一月用数字 10 表示....而对于 LocalDate,十月用数字 10 表示,十一月用数字 11 表示....

我正在处理他们使用 GregorianCalendar 的现有应用程序。现在我想将通过方法调用收到的 LocalDate 值转换为 GregorianCalendar 格式,以便匹配月份值。

我已经搜索了很多博客都无法转换值。下面是我试过但仍然无法将日期格式更改为 GregorianCalendar 格式的代码。

java代码:

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
class Convert{
    public static String format(GregorianCalendar calendar){
        SimpleDateFormat fmt = new SimpleDateFormat("dd-M-yyyy");
        fmt.setCalendar(calendar);
        String dateFormatted = fmt.format(calendar.getTime());
        System.out.println("--date formatted--- " + dateFormatted);
        return dateFormatted;
    }
    void convertLocalDateToGregorianCalendar(){
        LocalDate localDate = new LocalDate();
        DateTime dateTimeObj = localDate.toDateTimeAtStartOfDay();
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeInMillis(dateTimeObj.getMillis());
        String formattedGCDate = format(gc);
        System.out.println("converted LocalDate to GregorianDate date value " + formattedGCDate);
    }
    public static void main(String[] args) {
                new Convert().convertLocalDateToGregorianCalendar();         
} }

输出:

--date formatted--- 13-10-2016
converted LocalDate to GregorianDate date value 13-10-2016

输出中的预期日期值: 13-9-2016(公历十月用数字9表示)

PS: java5是我用的版本

我认为您不能直接使用 SimpleDateFormat 来格式化公历日期。 我有两个建议可以解决:

1.If 您不关心重用 calendar.getTime() 您可以在 fmt.format:

之前将月份滚动(或添加)-1
SimpleDateFormat fmt = new SimpleDateFormat("dd-M-yyyy");
fmt.setCalendar(calendar);    
calendar.roll(Calendar.MONTH, -1); //or add
String dateFormatted = fmt.format(calendar.getTime());
System.out.println("--date formatted--- " + dateFormatted);

2.Don不使用 SimpleDateFormat,calendar.get(Calendar.MONTH) 将 return 9 如您所愿:

public static String format(GregorianCalendar calendar){
    String dateFormatted = String.format("%s-%s-%s", calendar.get(Calendar.DATE),
                            calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR));
    System.out.println("--date formatted--- " + dateFormatted);
    return dateFormatted;
}

tl;博士

java.util.GregorianCalendar.from( 
    java.time.LocalDate.parse( myJodaLocalDate.toString() )
    .atStartOfDay( ZoneId.of( "America/Montreal" ) )
)

详情

您正在混合使用两个截然不同的日期时间库:

  • Joda-Time
  • 旧版日期时间 类 与 Java
  • 捆绑在一起

旧的遗留日期时间 类 设计不佳、令人困惑且麻烦;避开他们。由 java.time 类.

补充

Joda-Time 项目非常棒,为 java.time 提供了灵感。但现在项目在 maintenance mode,团队建议迁移到 java.time 类。

java.time

默认将您的 org.joda.time.LocalDate 转换为 java.time.LocalDate by going through a String. Both use standard ISO 8601 格式,因此无需指定格式模式。

java.time.LocalDate ld = java.time.LocalDate.parse( myJodaLocalDate.toString() );

您显然需要一个日期时间值,因此我们需要为您的日期添加时间 LocalDate。显然你想从一天的第一刻开始。不要假设第一个时刻是 00:00:00,因为夏令时 (DST) 等异常可能意味着另一个时间,例如 01:00:00。让java.time决定时刻。您需要指定 desired/expected 时区以解决此类异常情况并调整 wall-clock time.

你问题中的代码忽略了这个关键的时区问题。如果忽略,则隐式应用 JVM 当前的默认时区。此默认值可以在 运行时随时更改。所以最好是明确的。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );

我强烈建议您坚持使用 java.time 类。但是,如果您绝对需要旧的遗留 类,例如与尚未更新到 java.time 的旧代码接口,那么您可以转换。查看添加到旧 类 的新方法。

GregorianCalendar gc = java.util.GregorianCalendar.from( zdt );

月份索引

该问题询问如何生成一个字符串,其中月份编号作为 1 月至 12 月的从零开始的索引 0-11,以匹配 GregorianCalendar 的内部工作方式。

坦率地说,回答这个问题是一种伤害。用从零开始的数字来给月份编号简直是疯了。这样做会造成无穷无尽的混乱。在 GregorianCalendar 中这样做从一开始就是一个非常糟糕的设计选择。它的使用应该被淘汰而不是被提升。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

Joda-Time 项目,现在在 maintenance mode,建议迁移到 java.time。

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time类?

  • Java SE 8 and SE 9 及更高版本
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
  • Android
    • ThreeTenABP项目专门为Android改编了ThreeTen-Backport(如上所述)。
    • 参见

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

如果我对问题的理解正确,我们正在混合 2 种东西

a) Calender / GregorianCalender 和实际日历本身中月份的内部表示。

你说得对的内部表示是从 0-11 表示一年中的 12 个月,人类对此的解释是一年中的 1-12 个月。当您调用格式操作时,您会得到日期显示在实际人类日历上的方式,即 October ,一年中的第 10 个月。内部表示仍然是9。如果你问如何,你可以使用API

查看
gc.setTimeInMillis(dateTimeObj.getMillis());
System.out.println(gc.get(Calendar.MONTH));

这会打印数字 9

如果你想要日期的内部表示,你也可以这样做。一个非常 hacky 的方法如下,虽然我不保证,但可以让你对事物有一个整体的了解。

LocalDate localDate = new LocalDate();
DateTime dateTimeObj = localDate.toDateTimeAtStartOfDay();
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(dateTimeObj.getMillis());
System.out.println(gc.get(Calendar.DAY_OF_MONTH) +"-"+ ("00"+ gc.get(Calendar.MONTH)).substring(1)  +"-"+gc.get(Calendar.YEAR));