我有下面的代码
public Long getEpochTime(String dateToGetItsEpoch) throws ParseException
{
TimeZone timeZone = TimeZone.getTimeZone("UTC");
final String REQUEST_DATE_FORMAT = "dd/MM/yyyy h:m";
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(dateToGetItsEpoch);
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);
format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());
Date d = cal.getTime();
return d.getTime();
}
如果我将设备的语言环境更改为其他语言,则总是以UTC时间作为返回值。哪个是正确的,但是我想知道这是怎么回事?设备如何知道我给它的日期是哪个时区,以便它相应地进行计算?
A Date
根本没有时区。默认情况下,SimpleDateFormat
用于解析和格式化。 Calendar
也是如此; Date
没有。
给出以下操作顺序:
TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(dateToGetItsEpoch);
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);
format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());
......最初是使用设备的默认时区parsing字符串,然后以UTC formatting字符串。请注意,Calendar
部分与此处无关-您将获得与以下相同的结果:
TimeZone timeZone = TimeZone.getTimeZone("UTC");
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date date = format.parse(dateToGetItsEpoch);
format.setTimeZone(timeZone);
final String utcTime = format.format(date);
我个人建议在Java中使用Joda Time进行日期/时间工作,请注意。它是一个比Calendar
/ Date
更干净的API。
Answer by Jon Skeet是正确的。这是一些更新的代码,以使用现代的[[java.time类取代了麻烦的旧式日期时间类。
格式化模式顺便说一下,您的格式选择不佳。相反,我建议使用设计用于交换日期时间值作为文本的标准ISO 8601格式。
12小时与24小时制
h
表示12小时制(而不是24小时制,即大写的H
或HH
)表示一个小时的一两位数字。因此,除非添加AM
或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点-所有这些时刻都相差几个小时。
要确定时刻,我们必须在一定程度上知道预期的时区。然后将该区域用作ZoneId
以得到ZonedDateTime
。然后我们到了片刻。Locale
不是时区
我的设备的语言环境到任何地方
A
Locale
具有nothing到时区
Locale
用于对表示日期时间对象的生成文本进行本地化。 要本地化,请指定:FormatStyle
确定字符串应该是多长或缩写。FormatStyle
确定:Locale
[您可能有魁北克省的工程师使用Locale
来制定人类语言和文化规范,但是在日本访问时使用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
您问:
设备如何知道我给它的日期是哪个时区,以便它相应地进行计算?
您正在使用可怕的日期时间类,而这些类却无法说明缺乏时区或UTC偏移量指示符的日期时间概念。因此,从技术上讲,在之前的那几天,您的代码是一团糟,无法破解的事情。 我建议花no努力尝试理解Joda-Time
及其后继者java.time
Africa/Tunis
和ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
的行为。只需继续使用java.time
,这是业界领先的日期时间处理框架。