Kotlin SimpleDateFormat 解析错误的时区

son*_*ntd 0 timezone simpledateformat kotlin

我的移动时区是 GMT+7,我有一个代码可以将特定日期时间(GMT+0)转换为特定时区(GMT+3):

var strDate = "2020-07-10 04:00:00+0000"
var result: Date?
var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ")
dateFormatter.timeZone = TimeZone.getTimeZone("Asia/Jerusalem")
result = dateFormatter.parse(strDate)
Run Code Online (Sandbox Code Playgroud)

问题是结果总是返回“ Fri Jul 10 11:00:00 GMT+07:00 2020
,但我预计它将返回日期对象“ Fri Jul 10 07:00:00 GMT+03:00 2020 ”,知道是什么我的代码有问题吗?

deH*_*aar 5

建议使用java.time和停止使用java.util.Datejava.util.Calendar以及java.text.SimpleDateFormat因为像这样的问题。

在您的代码中,目标时区显然没有应用于日期,但原因并不明显。

另一个问题可能是您正在使用的模式,因为您的示例String不包含任何小于秒的时间单位,但该模式尝试考虑.SSS(这使得代码在 Kotlin Playground 中失败)。

切换到java.time现代类并处理它,例如OffsetDateTime解析它String(它不包含有关特定时区的信息,只是零小时的偏移量)并ZonedDateTime作为目标对象(这考虑了可能有不同的实时时区)偏移量取决于夏令时等因素)。

你可以这样做:

import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter

fun main() {
    // this example is in UTC (+0000 --> no offset / offset of 0 hours)
    var strDate = "2020-07-10 04:00:00+0000"
    // create a formatter that can parse Strings of this pattern
    // ([] represents optional units to be parsed)
    var dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss[.SSS]Z")
    // and parse the String to an OffsetDateTime using this formatter
    var resultOfParsing = OffsetDateTime.parse(strDate, dateFormatter)
    // then print the parsed result
    println(resultOfParsing)
    
    // create the target time zone
    var timeZone = ZoneId.of("Asia/Jerusalem")
    // then use the target zone for a zone shift
    var jerusalemTime: ZonedDateTime = resultOfParsing.atZoneSameInstant(timeZone)
    // and print the result
    println(jerusalemTime)
    // you could use your formatter defined above for a differently formatted output, too
    println(jerusalemTime.format(dateFormatter))
}
Run Code Online (Sandbox Code Playgroud)

其输出(包括所有中间结果):

2020-07-10T04:00Z
2020-07-10T07:00+03:00[Asia/Jerusalem]
2020-07-10 07:00:00.000+0300
Run Code Online (Sandbox Code Playgroud)