我知道这个话题已被打死,但在搜索了几个小时后我不得不问这个问题。
我的问题:根据客户端应用程序(iphone)的当前时区对服务器上的日期进行计算。客户端应用程序会在几秒钟内告诉服务器它的时区离GMT有多远。我想使用此信息对服务器中的日期进行计算。服务器上的日期都存储为UTC时间。 所以我希望在将UTC Date对象转换为此本地时区后获得它的HOUR。
我目前的尝试:
int hours = (int) Math.floor(secondsFromGMT / (60.0 * 60.0));
int mins = (int) Math.floor((secondsFromGMT - (hours * 60.0 * 60.0)) / 60.0);
String sign = hours > 0 ? "+" : "-";
Calendar now = Calendar.getInstance();
TimeZone t = TimeZone.getTimeZone("GMT" + sign + hours + ":" + mins);
now.setTimeZone(t);
now.setTime(someDateTimeObject);
int hourOfDay = now.get(Calendar.HOUR_OF_DAY);
变量小时和分钟表示当地时区远离GMT的小时和分钟。调试此代码后 - 变量小时,分钟和符号都是正确的。
问题是hourOfDay没有返回正确的小时 - 它返回UTC时间而不是当地时间的小时。想法?
答案 0 :(得分:3)
您的时区字符串配置错误。试试这个,
String sign = secondsFromGMT > 0 ? "+" : "-";
secondsFromGMT = Math.abs(secondsFromGMT);
int hours = secondsFromGMT/3600;
int mins = (secondsFromGMT%3600)/60;
String zone = String.format("GMT%s%02d:%02d", sign, hours, mins);
TimeZone t = TimeZone.getTimeZone(zone);
答案 1 :(得分:0)
获取UTC Date对象转换为此本地时区后的HOUR
区域(首选)
ZonedDateTime.now(
ZoneId.of( "Africa/Tunis" ) // Use a zone rather than a mere offset-from-UTC whenever possible.
).getHour()
23
<强>偏移强>
OffsetDateTime.now(
ZoneOffset.ofTotalSeconds( secondsFromGMT ) // Use a mere offset-from-UTC only when the appropriate zone is unavailable AND you have been assured this particular offset is correct for your input data.
).getHour()
23
你正在使用现在遗留下来的麻烦的旧日期时间类,取而代之的是现代业界领先的java.time类。
以UTC Instant
获取当前UTC时刻。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant instant = Instant.now() ;
调整到特定时区。
Specify a [proper time zone name](https://en.wikipedia.org/wiki/List_of_tz_zones_by_name) in the format of `continent/region`, such as [`America/Montreal`](https://en.wikipedia.org/wiki/America/Montreal), [`Africa/Casablanca`](https://en.wikipedia.org/wiki/Africa/Casablanca), or `Pacific/Auckland`. Never use the 3-4 letter abbreviation such as `EST` or `IST` as they are *not* true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
如果在运行时您想要JVM的当前默认时区,请询问它。请记住,这可以随时改变 。因此,如果关键,您应该向用户询问或确认。
ZoneId z = ZoneId.systemDefault() ;
应用时区以生成ZonedDateTime
对象。
ZonedDateTime zdt = instant.atZone( z ) ;
你说你只想从这个划定日期的时间开始。询问特定方法。
int hourOfDay = zdt.getHour() ;
顺便说一句,您可能会发现LocalTime
类很有用。
LocalTime lt = zdt.toLocalTime() ;
变量小时和分钟表示当地时区远离GMT的小时和分钟
不,不是时区。 您已将带有偏移的区域合并。理解这种区别非常重要。
特殊偏移可能在多个地方巧合使用。例如,有时候都柏林,伦敦,卡萨布兰卡,拉各斯和布拉柴维尔都会在UTC前一小时共享相同的+01:00
偏移量。但在其他时候,他们可能不会,例如在今年冬天,当拉各斯比UTC早一个小时,而其他三个在UTC之前切换到零时(即UTC本身)。
使用区域和片刻,您可以确定偏移量。但不是朝另一个方向走;如果只有偏移,则无法可靠地确定区域。
所以你的小时和分钟数只是一个补偿。对于输入的特定日期,您的区域的偏移量可能不正确。所以总是喜欢时区而不仅仅是偏移。
OffsetDateTime
如果您因某种原因而被卡住了,您确定对于您的指定输入是正确的,但您不知道时区,请使用ZoneOffset
&amp; OffsetDateTime
而不是ZoneId
&amp; ZonedDateTime
。但是,如果可能的话,使用区域而不是偏移,如上所述。
ZoneOffset offset = ZoneOffset.ofTotalSeconds( secondsFromGMT ) ;
OffsetDateTime odt = OffsetDateTime.now( offset ) ;
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。