以Java格式获取UTC格式的日期对象

时间:2014-02-28 09:27:49

标签: java simpledateformat

我写了以下代码。我想以UTC格式获取Date对象。

我可以使用SimpleDateFormat以UTC格式获得预期的日期字符串。但是使用相同的SimpleDateFormat对象,我无法以UTC格式获取对象。它以IST格式返回对象。

搜索后,我发现Date对象不存储时间戳信息。

如何以UTC格式获取日期对象?

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class dddd {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Input - "+1393572325000L);
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date= new Date(1393572325000L);  
        String dateString = formatter.format(date);

        System.out.println("Converted UTC TIME (using Format method) : "+dateString);

        Date date2 =null;
        try {
            date2 = formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }


        System.out.println("Parsed Date Object (using Parse method) : "+date2);

        System.out.println("Expected Date Object : Fri Feb 28 07:25:25 UTC 2014");

    }

}

这将打印以下输出:

Input - 1393572325000
Converted UTC TIME (using Format method) : 2014-02-28 07:25:25
Parsed Date Object (using Parse method) : Fri Feb 28 12:55:25 IST 2014
Expected Date Object : Fri Feb 28 07:25:25 UTC 2014

5 个答案:

答案 0 :(得分:37)

final Date currentTime = new Date();
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC time: " + sdf.format(currentTime));

答案 1 :(得分:23)

日期没有任何时区。您所看到的只是Date.toString()方法的日期格式,它始终使用您的本地时区将与时区无关的日期转换为您可以理解的字符串。

如果要使用UTC时区将时区不可知日期显示为字符串,请使用带有UTC时区的SimpleDateFormat(正如您在问题中所做的那样)。

换句话说,时区不是日期的属性。它是用于将日期转换为字符串的格式的属性。

答案 2 :(得分:15)

TL;博士

Instant.ofEpochMilli ( 1_393_572_325_000L )
       .toString()
  

2014-02-28T07:25:25Z

详细

(a)你似乎对日期是什么感到困惑。正如answer by JB Nizet所述,日期跟踪自Unix时区内epoch UTC(1970年第一时刻)以来的毫秒数(即没有时间)区域偏移)。所以Date没有时区。它没有“格式”。我们从日期值创建字符串表示,但日期本身不是字符串且没有字符串

(b)您指的是“UTC格式”。 UTC不是一种格式,我没有听说过。 UTC (Coordinated Universal Time)是时区的起点。位于伦敦格林威治皇家天文台以东的时区是几个小时的时间段。比UTC早几分钟。西进时区落后于UTC。

您似乎指的是ISO 8601格式化的字符串。您正在使用可选格式,省略(1)中间的T,以及(2)结束时的UTC偏移量。除非在应用程序的用户界面中向用户显示字符串,否则我建议您通常坚持使用通常的格式:

  • 2014-02-27T23:03:14+05:30
  • 2014-02-27T23:03:14Z(Zulu为'Z',或UTC,偏移量为+00:00)

(c)避免使用3或4个字母的时区代码。它们既不标准也不独特。例如,“IST”可以表示印度标准时间爱尔兰标准时间

(d)在发布之前花些精力搜索StackOverflow。你会找到你所有的答案。

(e)避免使用java.util.Date&与Java捆绑在一起的日历类。众所周知,它们很麻烦。使用Joda-Time库或Java 8的新java.time包(受Joda-Time启发,由JSR 310定义)。

java.time

在解析和生成字符串时,java.time类默认使用标准的ISO 8601格式。

OffsetDateTime odt = OffsetDateTime.parse( "2014-02-27T23:03:14+05:30" ); 
Instant instant = Instant.parse( "2014-02-27T23:03:14Z" );

解析自UTC 1970年第一时刻以来的毫秒数。

Instant instant = Instant.ofEpochMilli ( 1_393_572_325_000L );
  

instant.toString():2014-02-28T07:25:25Z

Instant调整为所需的时区。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
  

zdt.toString():2014-02-28T02:25:25-05:00 [美国/蒙特利尔]


关于 java.time

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

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore


约达时间

更新:现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

Joda-Time使用ISO 8601作为默认值。

Joda-Time DateTime对象知道它在指定的时区,与java.util.Date对象不同。

通常最好明确指定时区而不是依赖默认时区。

示例代码

long input = 1393572325000L;
DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );

DateTimeZone timeZoneIndia = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneIreland = DateTimeZone.forID( "Europe/Dublin" );

DateTime dateTimeIndia = dateTimeUtc.withZone( timeZoneIndia );
DateTime dateTimeIreland = dateTimeIndia.withZone( timeZoneIreland );

// Use a formatter to create a String representation. The formatter can adjust time zone if you so desire.
DateTimeFormatter formatter = DateTimeFormat.forStyle( "FM" ).withLocale( Locale.CANADA_FRENCH ).withZone( DateTimeZone.forID( "America/Montreal" ) );
String output = formatter.print( dateTimeIreland );

转储到控制台...

// All three of these date-time objects represent the *same* moment in the timeline of the Universe.
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "dateTimeIreland: " + dateTimeIreland );

System.out.println( "output for Montréal: " + output );

跑步时......

dateTimeUtc: 2014-02-28T07:25:25.000Z
dateTimeIndia: 2014-02-28T12:55:25.000+05:30
dateTimeIreland: 2014-02-28T07:25:25.000Z
output for Montréal: vendredi 28 février 2014 02:25:25

实际上,java.util.Date 确实有时区。该时区在其源代码中分配得很深。然而,为了大多数实际目的,该课程忽略了该时区。其toString方法应用JVM的当前默认时区而不是内部时区。混乱?是。这是避免使用旧的java.util.Date/.Calendar类的众多原因之一。改为使用java.time和/或Joda-Time。

答案 3 :(得分:6)

在java 8中,使用 java 8 java.time.Instant 库,很容易获得UTC时间戳:

Instant.now();

这几段代码将返回UTC时间戳。

答案 4 :(得分:2)

您可以从现在开始减去时区差异。

final Calendar calendar  = Calendar.getInstance();
final int      utcOffset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
final long     tempDate  = new Date().getTime();

return new Date(tempDate - utcOffset);