将字符串转换为Java中的日历对象


173

我是Java新手,通常使用PHP。

我正在尝试转换此字符串:

2011年3月14日星期一格林尼治标准时间16:02:37

放入Calendar对象,以便我可以像这样轻松地提取Year和Month:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

手动解析它不是一个好主意吗?使用子串方法?

任何建议将帮助谢谢!


Answers:


395
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

注意:Locale根据您的环境/要求进行设置


也可以看看


onlineconversion.com/unix_time.htm。这是在线时间戳转换器。由Java代码计算的值与此在线转换得到的值不同。为什么??您能否通过这个。谢谢:)
Sachin J

6
请注意,这会丢失时区信息。Calendar对象将具有系统默认的TimeZone而不是已解析的TimeZone。
克里斯蒂安·克拉比

这不再是最重要/可接受的答案。由于Java 8已经发布超过4年,因此应该更新答案以提及java.time。这个问题在Google上非常突出。
Scolytus

18

tl; dr

现代方法使用java.time类。

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011-03

避免使用旧的日期时间类

现代方法是使用java.time类。诸如此类的旧日期时间类Calendar设计证明设计不当,令人困惑且麻烦。

定义一个自定义格式化程序以匹配您的字符串输入。

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

解析为ZonedDateTime

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

您对年度和月份感兴趣。java.time类包括YearMonth用于该目的的类。

YearMonth ym = YearMonth.from( zdt );

您可以根据需要询问年和月的数字。

int year = ym.getYear();
int month = ym.getMonthValue();

但是该toString方法会生成标准ISO 8601格式的字符串。

String output = ym.toString();

全部放在一起。

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

转储到控制台。

System.out.println( "input: " + input );
System.out.println( "zdt: " + zdt );
System.out.println( "ym: " + ym );

输入:2011年3月14日星期一格林尼治标准时间

zdt:2011-03-14T16:02:37Z [GMT]

ym:2011-03

现场代码

请参阅在IdeOne.com中运行的代码

转换次数

如果必须有一个Calendar对象,则可以GregorianCalendar使用添加到旧类的新方法转换为。

GregorianCalendar gc = GregorianCalendar.from( zdt );

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


14

好吧,我认为复制像这样的类中已经存在的代码将是一个坏主意SimpleDateFormat

在另一方面,我个人会建议避免CalendarDate完全如果可以的话,并使用约达时间,而不是作为一个更好的设计的日期和时间API。例如,你需要是知道SimpleDateFormat不是线程安全的,所以你要么需要线程本地人,同步,或一个新实例每次使用它的时候。Joda解析器和格式化程序线程安全的。


感谢您的投入,我肯定会在将来使用Joda,它可能会非常有用
Doug Molineux

@Jon Skeet Joda不会在Android中反序列化。除非不需要保存日期和时间,否则乔达一文不值。
Frank Zappa

@FrankZappa:我不同意这一点-您可以在Joda Time中进行所有日期/时间计算,但是为了序列化目的,可以转换为其他类型(为简单起见,可能只是字符串)。
乔恩·斯基特

抱歉,必须投下赞成票,答案太旧了,它已经不是最高排名的答案了。今天java.time是路要走,罗勒·布尔克(Basil Bourque)提供了一个很好的答案。
Scolytus

2
@Scolytus:最高(且被接受)的答案是332票,而这个答案是10票。我认为,如果您现在对每一个有更好解决方案的7年以上的答案进行一次否决,那么您将用尽所有否决权……(我同意Basil的答案很好,我已经赞成了。)
乔恩·斯凯特(Jon Skeet)

10

无需创建新的日历,SimpleDateFormat已经在下面使用了日历。

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(我无法发表评论,这就是为什么我创建了一个新答案)


1
您的解决方案看起来不错,但有两个缺点:1. JavaDoc不保证行为符合预期。2.至少对于Java 6,您在行1353处找到一个克隆日历对象的路径。所以然后是!date.equals(cal.getTime())。
niels

5

SimpleDateFormat太好了,请注意HHhh上班时间不同。HH将返回24小时制小时,而hh将返回12小时制小时。

例如,以下将返回12小时时间:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

虽然这将返回24小时时间:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

4

用时区解析时间,Z模式为时区

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

输出:它将返回UTC时间

1508899140000

在此处输入图片说明

如果我们未将时区设置为yyyy-MM-dd'T'HH:mm:ssSimpleDateFormat将使用已设置的时区Setting



1

简单方法:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.