将"2010年1月2日"格式的String转换为Java格式的Date的最佳方式是什么?

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

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

将日期转换为时间.

推荐答案

这是一条艰难的道路,从Java1.1(1997)开始,这java.util.Date个setter方法就被弃用了.此外,自从Java8(2014)引入java.timeAPI以来,整个java.util.Date类实际上都被弃用(不推荐).

只需使用与输入字符串(the tutorial is available here)匹配的模式,使用DateTimeFormatter格式化日期.

在"2010年1月2日"作为输入字符串的特定情况下:

  1. "一月"是全文月份,因此使用MMMM模式
  2. "2"是一个月中较短的一天,因此使用d模式.
  3. "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(text, formatter)而不是LocalDate#parse(text, formatter).而且,如果您的格式模式碰巧也包含时区,则使用ZonedDateTime#parse(text, formatter).

以下是从the 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;

请注意,对于更流行的模式,它有几个predefined formatters.所以你可以用DateTimeFormatter.RFC_1123_DATE_TIME代替DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);.这是可能的,因为它们与SimpleDateFormat相反,是线程安全的.因此,如果有必要,您也可以定义自己的.

对于特定的输入字符串格式,您不需要使用显式的DateTimeFormatter:像2016-09-26T17:44:57Z这样的标准ISO 8601日期可以直接用LocalDateTime#parse(text)进行解析,因为它已经使用了ISO_LOCAL_DATE_TIME格式化程序.类似地,LocalDate#parse(text)解析不带时间分量的ISO日期(参见ISO_LOCAL_DATE),而ZonedDateTime#parse(text)解析添加了偏移和时区的ISO日期(参见ISO_ZONED_DATE_TIME).


前Java 8

如果您还没有使用Java8,或者被迫使用java.util.Date,那么可以使用与输入字符串匹配的格式模式,使用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参数的重要性.如果省略它,则它将使用输入字符串的月份名称中使用的不一定是英语的default locale.如果区域设置与输入字符串不匹配,那么即使格式模式看起来有效,您也会得到令人困惑的java.text.ParseException.

以下是从the 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

值得注意的是,SimpleDateFormatnot线程安全的.换句话说,永远不要将其声明为静态变量或实例变量并将其赋值,然后从不同的方法/线程中重用它.您应该始终在本地范围内创建全新的方法.

Java相关问答推荐

javafx getHostServices(). showDocument()调出Chrome而不是默认浏览器(Linux)

Cosmos Change Feed Process Lag远远超过收集中的记录数量

填写文本字段后锁定PDF

弹簧靴和龙目岛

CompleteableFuture是否运行在不同的内核上?

JavaFX如何在MeshView中修复多个立方体?

MimeMessage emlMessage=new MimeMessage(Session,emlInputStream);抛出InvocationTargetException

每次FXMLLoader调用ApplationConext.getBean(类)时创建@Component的新实例

%This内置函数示例

将PNG转换为位图自定义十六进制字符串

Java SSLKeyManager出厂密码

Spring Boot中的应用程序.properties文件中未使用的属性

我如何为我的Java抵押贷款代码执行加薪操作(&Q)

如何在Java springboot中从一个端点发送多个时间响应?

try 使用预准备语句占位符获取信息时出现Try-With-Resources错误

如何在ApacheHttpClient 5中为单个请求设置代理?

为什么项目名称出现在我的GET请求中?

Java List有一个在一个位置添加多个元素的方法,但我找不到一个在一个位置删除多个元素的方法

如何在Spring Security中设置一个任何人都可以打开的主页?

java构造函数中的冻结操作何时发生?