Grails中的时区转换导致错误的日期

时间:2018-10-16 13:03:47

标签: java grails calendar timezone

我要处理Grails(Java)中的时区。这里使用Java 7和Grails 2.3.7。

我有一个WebApp,其中为每个用户分配了一个timeZoneID。如果用户输入日期,则仅包含日期,月份和年份。我想自动设置时间。

用户输入的日期(例如,2018年10月1日,德语格式)应以UTC格式保存在数据库(MySQL)中。 向用户显示日期后,日期会根据用户的时区进行格式化。

许多timeZoneID与我的代码(欧洲/柏林,Hont_Kong等)都可以正常工作,但是例如America / New_York却不行,我也不明白为什么。

用于解析和保存日期的代码如下:

//endDate is 31.10.2018
def format = messageService.getMessage(code: 'default.date.short.format')

//--> dd.MM.yyyy for DE and MM/dd/yy for EN
println("Use format: " + format)

SimpleDateFormat sdf = new SimpleDateFormat(format);

//set timezone (America/New_York)
sdf.setTimeZone(TimeZone.getTimeZone(user.timeZoneID))

//parse endDate
Date parsedEndDate = sdf.parse(endDate)

//create a calendar instance (e.g. America/New_York)
Calendar calendarEnd = Calendar.getInstance(TimeZone.getTimeZone(user.timeZoneID));

//set time
calendarEnd.setTime(parsedEndDate);

//set hour/minute automatically
calendarEnd.set(Calendar.HOUR_OF_DAY, 23)
calendarEnd.set(Calendar.MINUTE, 59)

//at this point it should be 31.10.2018, 23:59 (german format, timezone America/New_York)

//Convert to UTC before saving date in DB (MySQL)
calendarEnd.setTimeZone(TimeZone.getTimeZone('UTC'))

//save the date
def obj = new Foo(date:calendarEnd).save(flush:true)

我的视图(gsp)中显示日期的代码如下:

<g:formatDate
        timeZone="${user.timeZoneID}"
        date="${fooInstance?.calendarEnd}"
        format="${message(code: 'default.date.format', default: 'MM/dd/yyyy, hh:mm a')}"/>

在DB内部,我得到2018-11-01 00:59:00 在我的视图(GSP)中,结果为31.10.2018,19:59,而不是31.10.2018,23:59

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

问题出在转换步骤:

//Convert to UTC before saving date in DB (MySQL)
calendarEnd.setTimeZone(TimeZone.getTimeZone('UTC'))

因为您只是在更改时区,所以它使用给定的时间和日期,就像它是UTC时区一样。

Java 1.7和更低版本在时间API方面有些笨拙,因此很多人使用Joda Time。

否则,您可以使用来自this question的建议,结果如下:

calendarEnd.add(Calendar.MILLISECOND, TimeZone.getTimeZone('UTC').getOffset(parsedEndDate.getTime())

这未经测试,可能是错误的,因为偏移量计算可能会有所不同