【问题标题】:How to convert Date based on String value for TimeZone如何根据时区的字符串值转换日期
【发布时间】:2014-02-08 16:56:35
【问题描述】:

我有一个日期对象,我需要将其转换为登录用户的时区。问题是时区在我们的数据库中仅表示为 GMT 的字符串值加上或减去以小时为单位的偏移量。例如,纽约时间的“GMT”或“GMT-5”或“GMT+5”。

当我只有“GMT-3”或“GMT+5”这样的字符串时,如何将我的日期对象转换为用户的时间?

提前感谢您的帮助。

【问题讨论】:

  • 你能改变你的数据库结构吗?如果您只是存储一个偏移量,那么将其存储为一个数字是明智的 - 请记住,并非所有偏移量都是小时数。另请注意,偏移量与时区不同。可以有多个时区当前具有相同的偏移量,但在其他时间会有不同的偏移量。
  • 另外,Date 对象不应该被“转换”。 Date 对象与时区无关。在将日期格式化为字符串或将字符串解析为日期时,您应该只关心时区。

标签: java date


【解决方案1】:

一个例子应该会有所帮助,但它似乎是 1 个字符 ISO 8601 time zone:

String myDate="2001-07-04T12:08:56GMT-3";

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'GMT'X");

if (myDate.indexOf("GMT-") >= myDate.length() -1 -4) {
    myDate = myDate.replace("-","-0");
}
if (myDate.indexOf("GMT+") >= myDate.length() -1 -4) {
    myDate = myDate.replace("+","+0");
}

System.out.println(format.parse(myDate));

它应该可以工作。

  • yyyy-MM-dd'T'HH:mm:ss'GMT'X 符合 iso8601 时区
  • myDate = myDate.replace("-","-0"); 将日期调整为您的格式

【讨论】:

  • 很好的例子。但请记住,SimpleDateFormat 不是线程安全的。使用数据库连接时,您通常会有一个线程池,并且由于缺少线程安全性而可能会遇到“奇怪的行为”。我会推荐 FastDateFormat,它的工作原理与 SimpleDateFormat 完全一样,但内置了线程安全:commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…
  • 是的,SimpledateFormat 不是线程安全的,因为同步可能会导致性能损失,并且创建新实例比同步更快。 FastDateFormat 应该是个好机会,但是不支持 iso8601 ....
【解决方案2】:

偏移量≠时区

正如 Jon Skeet 在评论中所说,时区不仅仅是与 UTC/GMT 的偏移量。存储偏移小时数(和分钟数)对于在数据库/存储中处理日期时间来说不是最佳策略。

乔达时间

java.util.Date 和 java.util.Calendar 类是出了名的麻烦。避开他们。使用Joda-Time。或者,在 Java 8 中,使用新的 java.time.* package,它由 JSR 310 定义,并受到 Joda-Time 的启发,但经过重新设计。

我们可以创建一个DateTimeZone 来表示偏移量,但如前所述,这在逻辑上并不构成完整的时区。

我们可以将 java.util.Date 对象直接传递给 Joda-Time DateTime 构造函数。除此之外,我们还传递了一个 DateTimeZone 对象。要进行另一个转换方向,请在 DateTime 对象上调用 toDate。

java.util.Date date = new java.util.Date(); // Retrieved from elsewhere. Faked here.

String offsetInput = "GMT-5";
int offsetHours = 0, offsetMinutes = 0;
offsetInput = offsetInput.replace( "GMT", "" ); // Delete 'GMT' characters.
String[] parts = offsetInput.split(":"); // About splitting a string: http://stackoverflow.com/q/3481828/642706

// Handle results of split.

if( parts.length == 0 ) {
    // Add some error handling here
} 

if ( parts.length >= 1 ) {
    offsetHours = Integer.parseInt( parts[0] ); // Retrieve text of first number (zero-based index counting).
}

if ( parts.length >= 2 ) {
    offsetMinutes = Integer.parseInt( parts[1] ); // Retrieve text of second number (zero-based index counting).
}

if( parts.length >= 3 ) {
    // Add some error handling here
} 

DateTimeZone partialTimeZoneWithOnlyOffset = DateTimeZone.forOffsetHoursMinutes( offsetHours, offsetMinutes );

DateTime dateTime = new DateTime( date, partialTimeZoneWithOnlyOffset );

转储到控制台…

System.out.println( "date: " + date ); // BEWARE: JVM's default time zone applied in the implicit call to "toString" of a Date. Very misleading.
System.out.println( "partialTimeZoneWithOnlyOffset: " + partialTimeZoneWithOnlyOffset );
System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime with alternate formatting: " + DateTimeFormat.forStyle( "FF" ).withLocale( Locale.US ).print(  dateTime ) );

运行时……

date: Sat Feb 08 22:40:57 PST 2014
partialTimeZoneWithOnlyOffset: -05:00
dateTime: 2014-02-09T01:40:57.810-05:00
dateTime with alternate formatting: Sunday, February 9, 2014 1:40:57 AM -05:00

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    相关资源
    最近更新 更多