当我创建一个新的Date对象时,它被初始化为当前时间,但在本地时区。如何获得当前的GMT日期和时间?


当前回答

这适用于在Android中获取UTC毫秒。

Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);  
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;

其他回答

博士tl;

Instant.now()   // Capture the current moment in UTC. 

生成一个String来表示该值:

Instant.now().toString()  

2016 - 09 - 13 - t23:30:52.123z

细节

正如Jon Skeet的正确答案所述,java.util.Date对象没有时区†。但是它的toString实现在生成日期-时间值的String表示时应用JVM的默认时区。让naïve程序员感到困惑的是,Date似乎有时区,但实际上没有。

java.util。Date、j.u.d alcalendar和Java .text. simpledateformat类与Java捆绑在一起是出了名的麻烦。避免它们。相反,可以使用以下两种有效的日期时间库:

java.time。*包在Java 8 Joda-Time

java。时间(java8)

Java 8带来了一个优秀的新Java .time。*包来取代旧的java.util。日期/日历类。

获取当前UTC/GMT时间是一个简单的一行程序…

Instant instant = Instant.now();

Instant类是java中的基本构建块。time,表示UTC时间轴上的一个时刻,分辨率为纳秒。

在Java 8中,当前时刻的捕获分辨率只有毫秒。Java 9带来了Clock的一个全新实现,它可以捕获当前时刻,最高可达该类的全部纳秒能力,这取决于您的主机时钟硬件的能力。

它的toString方法使用特定的ISO 8601格式生成其值的String表示形式。该格式根据需要输出0、3、6或9位数字(毫秒、微秒或纳秒)来表示秒的分数。

如果您想要更灵活的格式或其他附加特性,那么对于UTC本身应用零的offset-from-UTC (ZoneOffset。UTC常量)来获取OffsetDateTime。

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );

转储到控制台…

System.out.println( "now.toString(): " + now );

运行时……

now.toString(): 2014-01-21T23:42:03.522Z


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

Joda-Time项目现在处于维护模式,建议迁移到java。时间类。

你可以交换java。Time对象直接使用数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java。sql。*类。

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本——带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。


乔达时间

更新:Joda-Time项目现在处于维护模式,建议迁移到java。时间类。

使用第三方开源免费库Joda-Time,只需一行代码就可以获得当前日期-时间。

Joda-Time启发了新的java.time。类,但具有不同的架构。您可以在较旧版本的Java中使用Joda-Time。Joda-Time继续在Java 8中工作,并继续积极维护(截至2014年)。然而,Joda-Time团队建议迁移到java.time。

System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );

更详细的示例代码(Joda-Time 2.3)…

org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );

转储到控制台…

System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );

运行时……

Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z

有关执行时区工作的更多示例代码,请参阅我对类似问题的回答。

时区

我建议您始终指定一个时区,而不是隐式地依赖JVM当前的默认时区(它随时都可能改变!)。这种依赖似乎是日期时间工作中混乱和错误的常见原因。

调用now()时传递要分配的期望/期望时区。使用DateTimeZone类。

DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );

该类保存UTC时区的一个常量。

DateTime now = DateTime.now( DateTimeZone.UTC );

如果您确实希望使用JVM的当前默认时区,那么可以显式调用,以便代码是自文档化的。

DateTimeZone zoneDefault = DateTimeZone.getDefault();

ISO 8601

阅读ISO 8601格式。java。time和Joda-Time使用该标准的合理格式作为解析和生成字符串的默认值。


†实际上,java.util.Date确实有一个时区,深埋在源代码层之下。对于大多数实际目的,该时区将被忽略。因此,作为速记,我们说java.util.Date没有时区。此外,那个被埋没的时区不是Date的toString方法使用的时区;该方法使用JVM的当前默认时区。因此更有理由避免这个令人困惑的类,并坚持使用Joda-Time和java.time。

这是我的实现:

public static String GetCurrentTimeStamp()
{
    Calendar cal=Calendar.getInstance();
    long offset = cal.getTimeZone().getOffset(System.currentTimeMillis());//if you want in UTC else remove it .
    return new java.sql.Timestamp(System.currentTimeMillis()+offset).toString();    
}

date没有特定的时区,尽管它的值通常被认为与UTC有关。你凭什么认为现在是当地时间?

准确地说:java.util.Date中的值是自Unix epoch(发生在UTC时间1970年1月1日午夜)以来的毫秒数。同样的纪元也可以用其他时区来描述,但是传统的描述是用UTC来表示的。因为它是从一个固定的纪元开始的毫秒数,所以java.util.Date中的值在世界各地的任何特定时刻都是相同的,而不考虑当地的时区。

我怀疑问题是您通过使用本地时区的Calendar实例来显示它,或者可能使用同样使用本地时区的Date.toString(),或者默认情况下也使用本地时区的SimpleDateFormat实例。

如果这不是问题,请发布一些示例代码。

不过,我还是建议您使用Joda-Time,它提供了更清晰的API。

以特定时区和特定格式呈现系统时间的示例代码。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class TimZoneTest {
    public static void main (String[] args){
        //<GMT><+/-><hour>:<minutes>
        // Any screw up in this format, timezone defaults to GMT QUIETLY. So test your format a few times.

        System.out.println(my_time_in("GMT-5:00", "MM/dd/yyyy HH:mm:ss") );
        System.out.println(my_time_in("GMT+5:30", "'at' HH:mm a z 'on' MM/dd/yyyy"));

        System.out.println("---------------------------------------------");
        // Alternate format 
        System.out.println(my_time_in("America/Los_Angeles", "'at' HH:mm a z 'on' MM/dd/yyyy") );
        System.out.println(my_time_in("America/Buenos_Aires", "'at' HH:mm a z 'on' MM/dd/yyyy") );


    }

    public static String my_time_in(String target_time_zone, String format){
        TimeZone tz = TimeZone.getTimeZone(target_time_zone);
        Date date = Calendar.getInstance().getTime();
        SimpleDateFormat date_format_gmt = new SimpleDateFormat(format);
        date_format_gmt.setTimeZone(tz);
        return date_format_gmt.format(date);
    }

}

输出

10/08/2011 21:07:21
at 07:37 AM GMT+05:30 on 10/09/2011
at 19:07 PM PDT on 10/08/2011
at 23:07 PM ART on 10/08/2011

你可以使用的简单函数:

编辑:这个版本使用现代java。时间类。

private static final DateTimeFormatter FORMATTER
        = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss z");

public static String getUtcDateTime() {
    return ZonedDateTime.now(ZoneId.of("Etc/UTC")).format(FORMATTER);
}

方法返回值:

26-03-2022 17:38:55 UTC

最初的功能:

 public String getUTC_DateTime() {
    SimpleDateFormat dateTimeFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z");
    dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//gmt
    return dateTimeFormat.format(new Date());

}

以上函数返回:

26-03-2022 08:07:21 UTC