什么是最好的方法转换格式的字符串' 1月2日,2010年'到一个日期在Java?

最后,我希望将月、日和年分解为整数,以便我可以使用

Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();

将日期转换为时间。


当前回答

啊,又是Java Date的讨论。为了处理日期操作,我们使用date、Calendar、GregorianCalendar和SimpleDateFormat。例如,用你一月份的日期作为输入:

Calendar mydate = new GregorianCalendar();
String mystring = "January 2, 2010";
Date thedate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(mystring);
mydate.setTime(thedate);
//breakdown
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

然后你可以用类似这样的东西来操纵它:

Calendar now = Calendar.getInstance();
mydate.set(Calendar.YEAR,2009);
mydate.set(Calendar.MONTH,Calendar.FEBRUARY);
mydate.set(Calendar.DAY_OF_MONTH,25);
mydate.set(Calendar.HOUR_OF_DAY,now.get(Calendar.HOUR_OF_DAY));
mydate.set(Calendar.MINUTE,now.get(Calendar.MINUTE));
mydate.set(Calendar.SECOND,now.get(Calendar.SECOND));
// or with one statement
//mydate.set(2009, Calendar.FEBRUARY, 25, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

其他回答

此外,SimpleDateFormat对于某些客户端技术(如GWT)是不可用的。

使用Calendar.getInstance()是个好主意,您的要求是比较两个日期;长时间约会。

虽然有些答案在技术上是正确的,但它们并不可取。

The java.util.Date & Calendar classes are notoriously troublesome. Because of flaws in design and implementation, avoid them. Fortunately we have our choice of two other excellent date-time libraries: Joda-TimeThis popular open-source free-of-cost library can be used across several versions of Java. Many examples of its usage may be found on StackOverflow. Reading some of these will help get you up to speed quickly. java.time.* packageThis new set of classes are inspired by Joda-Time and defined by JSR 310. These classes are built into Java 8. A project is underway to backport these classes to Java 7, but that backporting is not backed by Oracle. As Kristopher Johnson correctly noted in his comment on the question, the other answers ignore vital issues of: Time of DayDate has both a date portion and a time-of-day portion) Time ZoneThe beginning of a day depends on the time zone. If you fail to specify a time zone, the JVM's default time zone is applied. That means the behavior of your code may change when run on other computers or with a modified time zone setting. Probably not what you want. LocaleThe Locale's language specifies how to interpret the words (name of month and of day) encountered during parsing. (The answer by BalusC handles this properly.) Also, the Locale affects the output of some formatters when generating a string representation of your date-time.

乔达时间

下面是关于Joda-Time的一些注意事项。

时区

在Joda-Time中,DateTime对象真正知道自己分配的时区。这与java.util.Date类形成对比,后者似乎有时区,但实际上没有。

请注意,在下面的示例代码中,我们如何将一个时区对象传递给解析字符串的格式化程序。该时区用于将日期-时间解释为发生在该时区。因此,您需要考虑并确定由字符串输入表示的时区。

由于您的输入字符串中没有时间部分,所以Joda-Time将指定时区的第一个时刻分配为一天的时间。通常这意味着00:00:00,但并不总是如此,因为日光节约时间(DST)或其他异常情况。顺便说一下,你可以通过调用withTimeAtStartOfDay对任何DateTime实例做同样的事情。

格式化程序模式

格式化程序模式中使用的字符在Joda-Time中类似于java.util中的字符。日期/日历,但不完全相同。仔细阅读诊断书。

不变性

我们通常在Joda-Time中使用不可变类。我们不会修改现有的Date-Time对象,而是调用基于其他对象创建新实例的方法,复制大多数方面(除非需要更改的地方除外)。下面最后一行中的withZone调用就是一个例子。不可变性有助于使Joda-Time非常线程安全,也可以使一些工作更加清晰。

转换

你将需要java.util.Date对象与其他不知道Joda-Time对象的类/框架一起使用。幸运的是,来回移动非常容易。

从java.util.Date对象(这里命名为date)到Joda-Time DateTime…

org.joda.time.DateTime dateTime = new DateTime( date, timeZone );

从Joda-Time到java.util.Date对象……

java.util.Date date = dateTime.toDate();

示例代码

String input = "January 2, 2010";

java.util.Locale locale = java.util.Locale.US;
DateTimeZone timeZone = DateTimeZone.forID( "Pacific/Honolulu" ); // Arbitrarily chosen for example.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMMM d, yyyy" ).withZone( timeZone ).withLocale( locale );
DateTime dateTime = formatter.parseDateTime( input );

System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime in UTC/GMT: " + dateTime.withZone( DateTimeZone.UTC ) );

运行时……

dateTime: 2010-01-02T00:00:00.000-10:00
dateTime in UTC/GMT: 2010-01-02T10:00:00.000Z

这是一种困难的方法,而且这些Java .util. date setter方法自Java 1.1(1997)以来就已经弃用了。此外,自java引入以来,整个java.util. date类实际上已被弃用(不推荐)。Java 8(2014)中的时间API。

只需使用DateTimeFormatter与输入字符串匹配的模式格式化日期(本教程可在此处获得)。

在“January 2, 2010”作为输入字符串的特定情况下:

“January”是全文月份,因此使用MMMM模式 “2”是一个月中最短的一天,所以使用d模式。 “2010”是4位数字的年份,所以使用yyyy模式。

String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02

注意:如果你的格式模式碰巧也包含时间部分,那么使用localdatetime# parse(文本,格式化程序)而不是localdatetime# parse(文本,格式化程序)。并且,如果您的格式模式碰巧也包含时区,那么使用ZonedDateTime#parse(文本,格式化器)代替。

下面是javadoc的相关摘录,列出了所有可用的格式模式:

Symbol Meaning Presentation Examples
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
Y week-based-year year 1996; 96
w week-of-week-based-year number 27
W week-of-month number 4
E day-of-week text Tue; Tuesday; T
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
F week-of-month number 3
a am-pm-of-day text PM
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-am-pm (1-24) number 0
H hour-of-day (0-23) number 0
m minute-of-hour number 30
s second-of-minute number 55
S fraction-of-second fraction 978
A milli-of-day number 1234
n nano-of-second number 987654321
N nano-of-day number 1234000000
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;

请注意,它为更流行的模式提供了几个预定义的格式化程序。所以不用例如DateTimeFormatter。ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);;这是可能的,因为与SimpleDateFormat相反,它们是线程安全的。因此,如果有必要,您也可以定义自己的。

对于特定的输入字符串格式,您不需要使用显式的DateTimeFormatter:标准的ISO 8601日期,如2016-09-26T17:44:57Z,可以直接使用LocalDateTime#parse(text)进行解析,因为它已经使用了ISO_LOCAL_DATE_TIME格式化器。类似地,LocalDate#parse(text)解析一个没有时间组件的ISO日期(参见ISO_LOCAL_DATE),而zoneeddatetime #parse(text)解析一个添加了偏移量和时区的ISO日期(参见iso_zoneed_date_time)。


Pre-Java 8

如果你还没有使用Java 8,或者被迫使用Java .util。日期,然后使用与输入字符串匹配的格式模式SimpleDateFormat格式化日期。

String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010

注意显式Locale参数的重要性。如果省略它,那么它将使用默认的语言环境,而不一定是输入字符串的月份名中使用的英语。如果区域设置与输入字符串不匹配,那么即使格式模式看起来有效,您也会混淆地得到java.text.ParseException。

下面是javadoc的相关摘录,列出了所有可用的格式模式:

Letter Date or Time Component Presentation Examples
G Era designator Text AD
y Year Year 1996; 96
Y Week year Year 2009; 09
M/L Month in year Month July; Jul; 07
w Week in year Number 27
W Week in month Number 2
D Day in year Number 189
d Day in month Number 10
F Day of week in month Number 2
E Day in week Text Tuesday; Tue
u Day number of week Number 1
a Am/pm marker Text PM
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
m Minute in hour Number 30
s Second in minute Number 55
S Millisecond Number 978
z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
Z Time zone RFC 822 time zone -0800
X Time zone ISO 8601 time zone -08; -0800; -08:00

注意,这些模式是区分大小写的,基于文本的四个字符或更多的模式表示完整的形式;否则,如果可能,则使用简短或缩写形式。所以,MMMMM或更多是不必要的。

下面是一些有效的SimpleDateFormat模式的例子,用于解析给定字符串的日期:

Input string Pattern
2001.07.04 AD at 12:08:56 PDT yyyy.MM.dd G 'at' HH:mm:ss z
Wed, Jul 4, '01 EEE, MMM d, ''yy
12:08 PM h:mm a
12 o'clock PM, Pacific Daylight Time hh 'o''clock' a, zzzz
0:08 PM, PDT K:mm a, z
02001.July.04 AD 12:08 PM yyyyy.MMMM.dd GGG hh:mm aaa
Wed, 4 Jul 2001 12:08:56 -0700 EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700 yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700 yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00 yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3 YYYY-'W'ww-u

重要的一点是,SimpleDateFormat不是线程安全的。换句话说,永远不要将它声明为静态变量或实例变量并将其赋值,然后从不同的方法/线程重用它。您应该始终在方法的局部范围内创建全新的方法。

我们使用了两个简单的格式化程序:

我们想要哪种格式的日期? 实际显示的是哪种格式日期?

我们解析完整的日期到时间格式:

date="2016-05-06 16:40:32";

public static String setDateParsing(String date) throws ParseException {

    // This is the format date we want
    DateFormat mSDF = new SimpleDateFormat("hh:mm a");

    // This format date is actually present
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-mm-dd hh:mm");
    return mSDF.format(formatter.parse(date));
}

试试这个

String date = get_pump_data.getString("bond_end_date");
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date datee = (Date)format.parse(date);