【问题标题】:Convert UTC date to current timezone将 UTC 日期转换为当前时区
【发布时间】:2016-09-26 06:33:47
【问题描述】:

我必须将格式为“2016-09-25 17:26:12”的 UTC 日期转换为 Android 的当前时区。我这样做了:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date myDate = simpleDateFormat.parse(temp.getString("date"));
System.out.println(mydate.toString());

这可行,但我不知道为什么它也会打印“GMT+02:00”。 这是输出:“Sun Sep 25 19:26:12 GMT+02:00 2016”,我不想显示“GMT+02:00”。

编辑,解决方案代码:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat outputSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date myDate = simpleDateFormat.parse(temp.getString("date"));
System.out.println(outputSdf.format(myDate));

【问题讨论】:

  • 您没有显示任何可以打印出任何内容的内容...如果您要打印出myDate.toString(),那正是Date.toString() 所做的。基本上你应该使用另一个SimpleDateFormat 来实现你想要的输出。
  • 是的,我正在打印 myDate.toString()
  • 所以不要那样做。使用 SimlleDateFormat 对其进行格式化。

标签: java android date


【解决方案1】:

tl;博士

LocalDateTime.parse( "2016-09-25 17:26:12".replace( " " , "T" ) )
             .atZoneSameInstant( ZoneId.systemDefault() )
             .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ) )

避免使用旧的日期时间类

您正在使用与最早版本的 Java 捆绑在一起的麻烦的旧日期时间类。现在被 java.time 类所取代。

ISO 8601

您输入的字符串几乎符合 java.time 类默认使用的标准ISO 8601 格式。将中间的空格替换为T

String input = "2016-09-25 17:26:12".replace( " " , "T" );

LocalDateTime

输入缺少offset-from-UTCtime zone 的任何指示。所以我们解析为LocalDateTime

LocalDateTime ldt = LocalDateTime.parse( input );

OffsetDateTime

您声称从应用的上下文中知道此日期时间值应为 UTC。因此,我们将该偏移量分配为常量ZoneOffset.UTC 以成为OffsetDateTime

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );

ZonedDateTime

您还说您想将此值调整为用户 JVM(或本例中的 Android 运行时)的当前默认时区。请注意,此默认设置可能会在您的应用执行期间随时更改。如果时区很关键,您应该明确询问用户所需/预期的时区。 ZoneId 类代表一个时区。

ZoneId z = ZoneId.systemDefault(); // Or, for example: ZoneId.of( "America/Montreal" )
ZonedDateTime zdt = odt.atZoneSameInstant( z );

生成字符串

你说你想生成一个字符串来表示这个日期时间值。您可以指定所需的任何格式。但通常最好让 java.time 根据Locale 对象中定义的人类语言和文化规范为您自动本地化。使用FormatStyle 指定长度或缩写(FULLLONGMEDIUMSHORT)。

Locale locale = Locale.getDefault();  // Or, for example: Locale.CANADA_FRENCH
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( locale );
String output = zdt.format( f );

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormat

Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

大部分 java.time 功能在ThreeTen-Backport 中向后移植到Java 6 和7,并进一步适应ThreeTenABP 中的Android(参见How to use…)。

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 我的项目目前用的是java7,没有你用的一些类,等我把项目移到java8后试试,谢谢解答。
  • @master94ga 重新阅读我的回答中倒数第二段,关于ThreeTen-BackportThreeTenABP
  • @BasilBourque(疯狂地笑...)谢谢朋友,您还遭受了人类白痴,名为时区地狱和日期格式的疯狂:)
【解决方案2】:

它打印 GMT+02 因为这是您的“本地”时区。 如果您想打印没有时区信息的日期,请使用 SimpleDateFormat 将日期格式化为您喜欢的格式。

编辑:添加代码示例(使用变量“myDate”)

SimpleDateFormat inputSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
inputSDF.setTimeZone(TimeZone.getTimeZone("UTC"));
Date myDate = inputSDF.parse("2016-09-25 17:26:12");
//
SimpleDateFormat outputSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(outputSDF.format(myDate));
System.out.println(TimeZone.getDefault().getID());

在(我的)控制台(使用我的本地时区)上输出。

2016-09-25 19:26:12
Europe/Paris

【讨论】:

  • 你能写代码吗,我希望日期格式为“yyyy-MM-dd HH:mm:ss”
  • 这样做的输出是在UTC时区而不是我的时区,如果我这样做outputSdf.setTimeZone(TimeZone.getTimeZone("UTC"));
  • 在不调用 setTimeZone 方法的情况下创建 SimpleDateFormat 实例意味着 SDF 实例将具有与您的 JVM 系统相同的 TimeZone。表明当您打印 myDate.toString() 并以“GMT+02:00”结束时,我可以确保您应该创建的实例默认具有您的本地时区。 除非您重用使用 UTC 创建的文件来进行解析
  • 谢谢,我的错误是我重用了使用 UTC 创建的实例
  • 不客气,请注意 java Date 对象没有时区“概念”,因此当您想将日期“点”转换为时区人类时间时,您应该使用 SimpleDateFormat表示(又名:格式化日期:))
【解决方案3】:

你可以使用:

system.out.println(myDate.getDay()+" "+myDate.getMonth()+" "+myDate.getYear());

放你需要的东西

【讨论】:

  • 这应该可以,但我不认为是最好的解决方案编辑:你说的方法也在 Android 中被弃用
【解决方案4】:

你可以用设置时区的方法来做到这一点。

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date myDate = simpleDateFormat.parse(rawQuestion.getString("AskDateTime"));

【讨论】:

  • 是我正在做的,转换工作,但它在输出中添加了“GMT+02:00”,我不想要它。
  • 尝试使用 TimeZone.getDefault().getDisplayName()
【解决方案5】:

下面是Date类的toString()实现:

public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }

如果您看到,它会将时区信息附加到日期。如果不想打印,可以使用SimpleDateFormatDate转为字符串,例如:

SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
System.out.println(format.format(new Date()));

【讨论】:

  • 只做 myDate.toString() 它在我的时区应用转换,格式保持 UTC
猜你喜欢
  • 2012-11-17
  • 2011-08-30
  • 2021-03-12
  • 1970-01-01
  • 2019-09-07
  • 1970-01-01
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多