我正在尝试读取格式为2019-12-23 13:35:00
的字符串以创建DateTime对象,并将其与我知道它对应的特定时区(GMT-5)关联
我正试图通过这种方式做到这一点:
val string1 = "2019-12-23 13:35:00"
val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
sdf.setTimeZone(StaticDateTimeZone.forID("Etc/GMT-5").toTimeZone)
val date = sdf.parse(string1)
输出不是我想要的,因为它不是假设datetime不在GMT-5时区,而是在系统的时区(GMT + 0)中,因此将datetime调整为GMT-5,例如:{{ 1}}
如何创建一个不会更改输入,而只是将时区与之关联的日期时间对象?
答案 0 :(得分:4)
似乎您正在使用JodaTime,然后转换为java.util.Date
。您可以直接使用Java 8中的java.time
软件包:
val string1 = "2019-12-23 13:35:00"
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val date = LocalDateTime.parse(string1, formatter)
date.atZone(ZoneId.of("Etc/GMT-5"))
给出:
date: java.time.LocalDateTime = 2019-12-23T13:35
res0: java.time.ZonedDateTime = 2019-12-23T13:35+05:00[Etc/GMT-5]
LocalDateTime
产生一个没有附加时区的日期。最后一行从上一个日期有效地创建了一个新的ZonedDateTime
,并在其顶部添加了给定的时区。如果您需要返回到java.util.Date
,请参见this answer。
答案 1 :(得分:4)
(使用Java语法而不是Scala)
我知道它对应的特定时区(GMT-5)
GMT-5
不是时区,而是纯偏移量。时区的名称为Continent/Region
,例如Africa/Tunis
。时区是区域使用的偏移量变化的历史记录。
您 不能根据偏移量可靠地确定时区。许多时区在特定时刻可能共享相同的偏移量,但在其他时刻可能有所不同。因此,您只会做出疯狂的猜测。仅当确定地知道特定时区时,才应用时区。
相反,使用偏移量本身来确定不带区域的时刻。这是一线解决方案。
LocalDateTime // Represent a date with time-of-day but lacking the context of an offset-from-UTC or a time zone.
.parse( // When parsing, no need to specify a formatting pattern when the input complies with the ISO 8601 standard.
"2019-12-23 13:35:00".replace( " " , "T" ) // Comply with ISO 8601 standard formatting, replacing SPACE in the middle with an uppercase `T`.
) // Returns a `LocalDateTime` object.
.atOffset( // Determine a moment by placing the date and time-of-day of a `LocalDateTime` into the context of an offset-from-UTC.
ZoneOffset.ofHours( -5 ) // Represent an offset-from-UTC with `ZoneOffset`, merely a number of hours-minutes-seconds ahead or behind the prime meridian.
) // Returns a `OffsetDateTime` object.
.toString() // Generate text in standard ISO 8601 format.
2019-12-23T13:35-05:00
您的输入字符串几乎采用ISO 8601标准格式。为了符合要求,请将中间的空格替换为T
。
String input = "2019-12-23 13:35:00".replace( " " , "T" ) ;
LocalDateTime
鉴于您的输入缺少时区或自UTC偏移,请解析为LocalDateTime
。
LocalDateTime ldt = LocalDateTime.parse( input ) ;
请注意,LocalDateTime
不是时间,不是时间轴上的一点。在您大约下午1:30的示例中,我们不知道这是否意味着日本东京为1:30 PM或美国俄亥俄州托莱多为1:30 PM,这两个小时相差很远。
OffsetDateTime
您声称肯定确定要通过UTC(通常在本初子午线以西)之后五小时的偏移量来观看此日期和时间。
ZoneOffset offset = ZoneOffset.ofHours( -5 ) ; // Five hours before UTC.
因此,我们将ZoneOffset
应用于OffsetDateTime
。
OffsetDateTime odt = ldt.atOffset( offset ) ;
请参阅此code run live at IdeOne.com。
odt.toString():2019-12-23T13:35-05:00
ZonedDateTime
时区总是比仅从UTC偏移更好。偏移量是小时-分钟-秒,仅此而已。时区更多。时区是特定区域的人们过去,现在和将来对偏移量的更改的历史记录。
但不要在某个时区猜测。仅当您知道LocalDateTime
对象最初用于该区域时,才应用区域。
以Continent/Region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Panama" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:0)
例如,我编写了一个方法:
public static Date getDateWithTimeZone(String dateString, String format, String timeZone) {
DateFormat df = new SimpleDateFormat(format);
Date dateObj = null;
try {
dateObj = df.parse(dateString);
DateTime dateTime = new DateTime(dateObj);
TimeZone zone = TimeZone.getTimeZone(timeZone);
return dateTime.withZoneRetainFields(DateTimeZone.forTimeZone(zone))
.toDate();
} catch (ParseException e) {
logger.error("Error while converting string to date",e);
}
return null;
}
答案 3 :(得分:0)
您可以执行以下操作:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDateTime = "2019-12-23 13:35:00";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(strDateTime, format);
ZoneId gmtZoneId = ZoneId.of("UTC+00:00");
ZoneId myZoneId = ZoneId.of("UTC-05:00");
System.out.println(format.format(ldt.atZone(gmtZoneId).withZoneSameInstant(myZoneId)));
}
}
输出:
2019-12-23 08:35:00
有用的文档:
You should not use SimpleDateFormat.
[更新]
根据Basil Bourque的评论发布以下代码:
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDateTime = "2019-12-23 13:35:00";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(strDateTime, format);
System.out.println(format.format(ldt.atZone(ZoneOffset.of("+00:00")).withZoneSameInstant(ZoneOffset.of("-05:00"))));
}
}
输出:
2019-12-23 08:35:00