java.time
Jon Skeet的答案是正确的。这是一些更新的代码以使用现代java.time类,这些类取代了麻烦的遗留日期时间类。
格式化模式
定义格式模式以匹配您的输入。
顺便说一句,您的格式选择不佳。相反,我建议使用为将日期时间值交换为文本而设计的标准ISO 8601格式。
12 小时制与 24 小时制
您的输入数据或格式模式存在缺陷。您使用了小写字母h
,这意味着 12 小时制中一个小时的一位或两位数字(而不是 24 小时制,即大写H
或HH
)。AM
因此,除非您添加一些or指示符,否则您的输入毫无意义PM
。我会假设你错误地从你的问题代码中省略了这个。
Locale locale = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu h:m a" ).withLocale( locale ) ;
LocalDateTime
将此类字符串解析为LocalDateTime
对象,因为它们缺少预期时区的指示符或与 UTC 的偏移量。
String input = "23/01/2020 4:5 PM" ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString(): 2020-01-23T16:05
片刻
我们上面得到的LocalDateTime
对象并不代表一个时刻,不是时间轴上的一个点。我们的时间是 23 日下午 4 点左右。但我们不知道这是否意味着东京、图卢兹或托莱多的下午 4 点——所有这些时刻相隔几个小时。
要确定某个时刻,我们必须确定预期的时区。然后将该区域应用为 aZoneId
以获得ZonedDateTime
. 然后我们就到了。
Locale
不是时区
我的设备的语言环境到任何地方
A与时区Locale
无关。ALocale
用于本地化生成的表示日期时间对象的文本。
要本地化,请指定:
例子:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f =
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l )
;
String output = myZonedDateTime.format( f );
您可能有一位来自魁北克的工程师,他使用Locale.CANADA_FRENCH
人类语言和文化规范,但在日本访问时使用Asia/Tokyo
时区来安排约会。
ZonedDateTime
回到你的LocalDateTime
对象。如果您确定它是为了代表突尼斯挂钟时间中的某个时刻,则应用时区Africa/Tunis
.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
您问:
设备如何知道哪个时区是我给它的日期,以便它进行相应的计算?
您正在使用糟糕的日期时间类,这些类未能解释缺少时区指示符或与 UTC 偏移量的日期时间的概念。所以从技术上讲,你的代码是一团糟,一个黑客,在Joda-Time及其继任者java.time之前的那些日子里是不可避免的。
我建议不费吹灰之力试图理解Date
&的行为Calendar
。继续使用java.time,业界领先的日期时间处理框架。