【问题标题】:Calender class and changed TimeZone conflicts日历类和更改 TimeZone 冲突
【发布时间】:2014-11-18 19:03:30
【问题描述】:

我想获得 日期格式 作为 yyyy-mm-ddT00:00:00不同的时区 作为输出。但是在这里我得到了日历日期的输出中的默认时区。

Code part as:-
Calendar cal =  Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    cal.set(Calendar.YEAR, 2014);
    cal.set(Calendar.MONTH, Calendar.NOVEMBER);
    cal.set(Calendar.DATE, 18);
    cal.set(Calendar.HOUR, 20);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
System.out.println("DateTime : " +  cal.getTime()+ " \n Zone :: "+ calFrom.getTimeZone().getDisplayName());

输出为:

DateTime : Wed Nov 19 05:30:00 IST 2014 
Zone :: Greenwich Mean Time

在这里,我将时区设置为 GMT 但日期显示 IST 以及如何将其转换为 2014-11-19T00:00:00 对应更改的时区。

【问题讨论】:

  • Date 对象与创建它的Calendar 对象的TimeZone 无关。
  • 如果你想在特定的日历/时区格式化,你应该使用DateFormat...
  • 我必须在一个 API 中实现它,该 API 采用 Calender 对象但适用于不同的时区。
  • 那么我怎样才能获得其他时区的日历参考。
  • @TarunChaudhary:根本不清楚你的意思 - “实施它”是什么意思?您已经有一个位于不同时区的日历,但您正在打印一个Date,并且没有有一个时区。

标签: java date calendar


【解决方案1】:

我想得到日期格式为 yyyy-mm-ddT00:00:00 和不同的 TimeZone 作为输出。

那么你需要使用一些描述的DateFormat,例如SimpleDateFormat。特别是,DateFormat 知道:

  • 格式
  • 用于月份名称等内容的语言环境
  • 时区
  • 日历系统

Date - 这是Calendar.getTime() 返回的内容 - 不知道任何。它只是表示一个时间点,可以用多种不同的方式表示。

你可能想要这样的东西:

TimeZone zone = TimeZone.getTimeZone("Etc/UTC");
Calendar cal =  Calendar.getInstance(zone);
cal.clear(Calendar.MILLISECOND);
cal.set(2014, Calendar.NOVEMBER, 18, 20, 0, 0); // Why 20 if you want an hour of 0?

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
format.setTimeZone(zone);

String text = format.format(cal.getTime());

【讨论】:

  • IST 和 GMT 有 6 小时 30 分钟的差异。如果我把 cal.set(Calendar.HOUR, 6); cal.set(日历.分钟,30);那么只有我得到 00:00:00。
  • @TarunChaudhary:不,IST 是 UTC+05:30。 (就本次讨论而言,GMT 和 UTC 是等价的 - 但通常最好谈论 UTC 以避免与英国时区混淆,英国时区观察 GMT 半年。)
  • @TarunChaudhary:你这是什么意思?目前尚不清楚您要实现什么您实际看到的...以及花 1 小时了解 IST 的问题。
【解决方案2】:

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

使用现代日期时间 API java.time 的解决方案:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zdtUtc = LocalDate.of(2014,Month.NOVEMBER, 18)
                                        .atTime(LocalTime.of(20, 0))
                                        .atZone(ZoneId.of("Etc/UTC"));
        System.out.println(zdtUtc);
    }
}

输出:

2014-11-18T20:00Z[Etc/UTC]

ONLINE DEMO

Trail: Date Time 了解有关现代日期时间 API 的更多信息。

您遇到的问题的解释:

java.util.Date 对象仅表示时间轴上的一个瞬间 — 自 UNIX 纪元(格林威治标准时间 1970 年 1 月 1 日 00:00:00)以来的毫秒数的包装。由于它不保存任何时区信息,它的 toString 函数应用 JVM 的时区以返回格式为 EEE MMM dd HH:mm:ss zzz yyyyString,从这个 毫秒 值。要以不同的格式和时区获取 java.util.Date 对象的 String 表示,您需要使用具有所需格式和适用时区的 SimpleDateFormat,例如

Date date = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);

sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);

sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);

来自 Ole V.V. 的宝贵评论:

如果我们不能避免得到一个老式的Calendar 对象,那么所有人 很可能它真的是GregorianCalendar,我们可以将其转换为 ZonedDateTime 只需使用 ((GregorianCalendar) cal).toZonedDateTime()。然后我们就设置好了。

另一个:

或者如果使用反向端口:DateTimeUtils.toZonedDateTime(cal)


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个Android项目工作并且您的Android API级别仍然不符合Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

  • 这是一个很好的答案。如果我们无法避免得到一个老式的Calendar 对象,那么很可能它确实是一个GregorianCalendar,我们可以简单地使用((GregorianCalendar) cal).toZonedDateTime() 将它转换为ZonedDateTime。然后我们就设置好了。
猜你喜欢
  • 1970-01-01
  • 2011-02-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 2018-07-11
  • 2015-11-04
  • 2014-12-27
  • 1970-01-01
相关资源
最近更新 更多