grails/mysql 时区更改

Posted

技术标签:

【中文标题】grails/mysql 时区更改【英文标题】:grails/mysql timezone change 【发布时间】:2011-03-24 09:02:15 【问题描述】:

完成更改应用时区的最佳方法是什么?在我看来,必须发生以下情况:

    系统管理员更改了服务器 TZ mysql 必须重启。 数据库中每个基于时间的列都必须使用 convert_tz 或等效方法更新所有值。因此,要么必须编写 mysql 脚本,要么必须编写一个 grails 脚本,为每个类加载每一行,更新所有时间字段。

显然,在发生这种情况时应该关闭服务器,并且必须做好备份以防出现错误。

有没有更好/更简单的方法来做到这一点?

【问题讨论】:

【参考方案1】:

Java 在使用日期时不使用时区;它将所有内容存储为 UTC,并且仅在显示日期时使用时区。有关 java 日期/时间的讨论,请参见以下链接。 http://www.odi.ch/prog/design/datetime.php

如果您在 MySQL 中使用 Date、Time 或 DateTime 列类型,则时区无关紧要。 如果您使用的是 TIMESTAMP 列类型,则时区可能很重要,因为 TIMESTAMP 存储为 UTC,但在检索和存储值时已完成转换。有关 MySQL 时区行为的讨论,请参见 http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html. 如果您担心在不同时区的多台服务器之间同步对象,事情会变得更加复杂,请参阅以下主题讨论此问题。 http://www.pubbs.net/201006/grails/2500-grails-user-how-to-get-gorm-to-store-dates-as-timestamp-in-utc-by-default-without-a-custom-hibernate-mapping-or-joda-time-plu.html

【讨论】:

我认为每当我们使用 new Date() 时,我们得到的时间是 JVM 的时区,它是从服务器的时区复制而来的。【参考方案2】:

我知道这是一个老问题,但我认为它也很永恒……至少,我最近偶然发现了很多次……所以我想我会贡献我的解决方案。

首先,我使用 Grails 2.5.1 和 PostgreSQL 9.4 作为后端。

其次,Groovy/Grails 中的日期字段在 PostgreSQL 中存储为timestamp without time zone。所以在我看来,上面的第一个答案实际上并不完全正确 - 日期没有存储在 UTC 中。这个观察让我思考......沿着“如果数据库不知道时区是什么,那么谁知道”的思路?而想到的第一个答案是“也许是春天”。

第三,我的问题的具体细节是我有很多日期是通过BootStrap.groovynew ThisClass().save() 引导到数据库中的。而且因为这些是日期,而不是日期 + 时间,它们看起来都像 2005-11-03 00:00:00 作为 PostgreSQL 时间戳(没有时区)。

第四,当我编辑我的一个 GSP 以在日期格式字符串中包含时区时,真正让我一分钱下降的原因,它显示为 PST(我的服务器所在的位置);当我在相关字段的g:formatDate 中包含timeZone="Asia/Kolkata" 时,时间提前了12h30。很明显,我的服务器在 PST8PDT 中运行,因为那不是 PostgreSQL,所以我回到 Spring 作为改变事物的潜在场所。

第五,在阅读了一些关于在 grails-app/conf/spring/resources.groovy 中设置语言环境的 cmets 之后,我决定尝试在那里设置语言环境和时区,如下所示:

// Place your Spring DSL code here
beans = 
    // from http://***.com/questions/1569446/grails-how-to-change-the-current-locale
    localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) 
        defaultLocale = new Locale("en","IN")
        java.util.Locale.setDefault(defaultLocale)
        println "configure spring/resources.groovy defaultLocale $defaultLocale"
        defaultTimeZone = TimeZone.getTimeZone("Asia/Kolkata")
        java.util.TimeZone.setDefault(defaultTimeZone)
        println "configure spring/resources.groovy defaultTimeZone $defaultTimeZone"
    

我还在所有日期字段中使用了g:format timezone="Asia/Kolkata" format="dd MMM, yyyy a z"。这似乎解释了 PostgreSQL timestamp 字段中正确时区和预期小时(即输入的小时)中的所有数据,即使日期最初是“在错误的时区”输入的。

第六,g:datePicker - 我阅读了许多关于使这个“时区敏感”的帖子,但我发现它的日期被解释为 Spring 使用的时区,所以在我的情况下,这正是我需要。相反,如果有人想在他们的语言环境中输入日期并让 Spring 即时将它们转换为服务器的时区,我想这需要一些额外的努力。

我个人认为如果g:datePicker 接受timeZone 作为参数并以与g:formatDate 相同的方式使用它会非常酷。

【讨论】:

【参考方案3】:

我们在使用 GORM 和使用 groovy.sql.Sql 之间存在时间差异问题(为了更快地导入数据)。

GORM 使用的是我们在 Bootstrap 中设置的 grails 配置时区 (UTC),但 groovy sql 使用的是默认系统时区 (GMT)。

通过在 $JAVA_OPTS 中设置时区解决了问题,尽管您可以将开关添加到 grails opts 或 run-app 命令。

grails -Duser.timezone=UTC run-app

【讨论】:

以上是关于grails/mysql 时区更改的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Grails 3 中更改应用程序名称?

Grails 2.3.5 在每次代码更改后都需要“grails clean”

在 IntelliJ/Grails 中更改 Ivy 缓存位置

Grails - 更改 javascript 后重新部署

Grails 3 - 更改运行应用程序的默认端口

在 Grails 中映射遗留数据库表时避免表更改?