如何使用Java中的UTC或GMT获取当前日期和时间?


479

当我创建一个新Date对象时,它将被初始化为当前时间,但是在本地时区。如何获取格林尼治标准时间的当前日期和时间?


我知道这些类型的主题已经完全讨论完了,但是我发现commons-lang包确实可以很好地处理这些常见的Java问题。commons.apache.org/lang/api-2.5/org/apache/commons/lang/time查看它们具有的各种软件包。

您想要哪个本地时间,以及达到什么精度。大多数时区是相对于UTC定义的,具有以SI秒为单位的固定偏移量,但是基于太阳观测和(略微)可变长度秒的GMT关系更为复杂。两者相差最多0.9秒。
mc0e

1
一个Date不成立的时区,所以“,但在当地时区”是不正确的(或不准确最好)见。所有关于java.util.Date
奥莱VV

Answers:


409

java.util.Date尽管它的值通常与UTC有关,但没有特定的时区。是什么让您认为这是当地时间?

确切地说:a内的值java.util.Date是自Unix时代(UTC)在1970年1月1日午夜开始的毫秒数。相同的纪元也可以在其他时区进行描述,但是传统的描述是以UTC表示的。由于自固定纪元以来的毫秒数,因此在java.util.Date世界各地的特定时刻,无论本地时区如何,其值都相同。

我怀疑问题在于您是通过使用本地时区的Calendar实例显示它,还是通过使用本地时区的Calendar实例显示(默认情况下也使用本地时区Date.toString()SimpleDateFormat实例)。

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

但是,无论如何,我还是建议您使用Joda-Time,它提供了更加清晰的API。


5
那可能是驱动程序问题。您可能需要将您的连接设置为UTC,或类似的设置。我以前见过类似的问题,但是问题不在java.util.Date中。
乔恩·斯基特

13
顺便说一句,根据stackoverflow.com/questions/4123534/…,MySQL JDBC驱动程序将给定java.util.Timestamp(或java.util.Date)转换为服务器时区。
Derek Mahar 2010年

5
@先生。猫:您如何确定?是写作System.out.println(new Date())吗?如果是这样,您应该知道toString()是在该时区应用该方法的方法...如果不是,请提供更多详细信息。
乔恩·斯基特

8
@KanagaveluSugumar:toString()始终使用默认时区。date.getTime()从Unix时代开始,绝对以毫秒为单位返回毫秒。最准确地说,它Date本身根本没有时区- 只是时间的瞬间,可以在多个时区中考虑。但是,当您创建实例时,它并不取决于您的时区。
乔恩·斯基特

6
@Jemenake:实际上,这并不是在格林威治午夜发生的,因为当时英国使用的是UTC + 1。只是历史的奇数之一。但是,我同意你的意思-最好说“新的Date()。getTime()返回自Unix时代以来的毫秒数,这是1970年1月1日UTC午夜开始”。因此,UTC是将时期限定在特定时间点的一部分,而不是结果的一部分。
乔恩·斯基特

323

tl; dr

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

生成一个字符串来表示该值:

Instant.now().toString()  

2016-09-13T23:30:52.123Z

细节

正如乔恩·斯凯特(Jon Skeet)的正确回答所指出的那样,java.util.Date对象没有时区。但是,toString当生成该日期时间值的String表示形式时,其实现将应用JVM的默认时区。令天真的程序员感到困惑的是,“日期” 似乎有一个时区,但没有。

java.util.Datej.u.Calendar以及java.text.SimpleDateFormat与Java绑定类是出了名的麻烦。避免他们。而是使用以下任何一种合格的日期时间库:

java.time(Java 8)

Java 8带来了一个出色的新java.time。*包,以取代旧的java.util.Date/Calendar类。

在UTC / GMT中获取当前时间是一个简单的方法。

Instant instant = Instant.now();

Instant类是java.time基本构建块,代表时间线上的时刻UTC,分辨率为纳秒

在Java 8中,当前时刻只能以毫秒级的分辨率捕获。Java的9带来了新鲜实施Clock捕获当前时刻到这个类的完整纳秒能力,这取决于你的主机计算机的时钟硬件的能力。

它的toString方法使用一种特定的ISO 8601格式生成其值的字符串表示形式。该格式根据需要输出零,三,六或九位数字(毫秒微秒纳秒)来表示的分数。

如果您想要更灵活的格式设置或其他附加功能,请对UTC本身(ZoneOffset.UTC常量)应用自UTC的偏移量零,以获取OffsetDateTime

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

转储到控制台...

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

运行时...

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

Java中的日期时间类型表,包括现代的和传统的。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

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

在哪里获取java.time类?

与哪个版本的Java或Android一起使用的哪个java.time库的表

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


乔达时代

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

使用Joda-Time 3rd-party开源免费库,您只需一行代码即可获取当前日期时间。

Joda-Time启发了Java 8中新的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。


2
DateTime.now().toDateTime(DateTimeZone.UTC)这就是我想要的!谢谢!
Managarm

1
@Managarm您可以将其缩短为:DateTime nowUtc = DateTime.now ( DateTimeZone.UTC ) ;
Basil Bourque

2014-01-21T15:34:29.933-08:00在您使用的示例中如何使用Pure Java 8做到这一点new org.joda.time.DateTime()
GOXR3PLUS,

1
@ GOXR3PLUS ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ).truncatedTo( ChronoUnit.MILLIS ).toOffsetDateTime().toString() 我们获取指定时区的当前时刻。接下来,关闭任何micros / nanos。然后,我们转换为仅具有距UTC的偏移量(小时-分钟-秒的数量),而不是拥有完整的时区(过去,现在和将来的历史变化),特定区域)。最后,我们OffsetDateTime根据默认toString方法中使用的标准ISO 8601格式生成表示该值的文本。
罗勒·布尔克

感谢您提供这个详细的说明,Android +1也支持+1 :) @BasilBourque
mochadwi

271
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));

//Local time zone   
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");

//Time in GMT
return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );

11
为什么在使用dateFormatGmt格式后使用dateFormatLocal进行解析...读起来没有意义。我敢肯定它是可行的,但是只是想知道吗?
MindWire 2012年

2
setTimeZone做到了(我想你也可以和GMT一样使用getTimeZone(“ UTC”)吗?)
rogerdpack

6
但是时间取决于设备设置时间。如果用户在设备上设置了错误的时间,那么您将得到错误的UTC。如果输入错误,请纠正我
Basavaraj Hampali 2013年

@BasavarajHampali,但在当今世界上,大多数设备都连接到互联网,可以纠正错误的时间
Akshat Agarwal

3
协调世界时(UTC)和格林威治标准时间(GMT)之间没有时差
时隙2014年

86

这肯定会返回UTC时间:作为String和Date对象!

static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

public static Date getUTCdatetimeAsDate() {
    // note: doesn't check for null
    return stringDateToDate(getUTCdatetimeAsString());
}

public static String getUTCdatetimeAsString() {
    final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    final String utcTime = sdf.format(new Date());

    return utcTime;
}

public static Date stringDateToDate(String StrDate) {
    Date dateToReturn = null;
    SimpleDateFormat dateFormat = new SimpleDateFormat(DATEFORMAT);

    try {
        dateToReturn = (Date)dateFormat.parse(StrDate);
    }
    catch (ParseException e) {
        e.printStackTrace();
    }

    return dateToReturn;
}

在我的回答中,我忘记显示DATEFORMAT的定义: static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
某处某人

21
请避免在Java中以大写字母开头的方法名称。有关方法名称,请参见Java编码约定
Florian Schrofner,2015年

2
重定向到该答案后new Date(),如果设备时间错误,则呼叫将永远不会返回正确的UTC时间。
Sanoop'3

这种方法获取时间是否取决于设备日历?
阿诺德·布朗

要注意的一件事。任何需要在UTC中获取日期或时间戳的解决方案,看起来关键是不要重用SimpleDateFormat,而是使用一个将UTC转换为字符串,然后在将字符串转换为Date时创建另一个UTC。或时间戳记对象。我注意到,如果您尝试重用相同的SimpleDateFormat,那么生成的Date / Timestamp对象将恢复为本地时区而不是UTC。
Brian Begun

65
    Calendar c = Calendar.getInstance();
    System.out.println("current: "+c.getTime());

    TimeZone z = c.getTimeZone();
    int offset = z.getRawOffset();
    if(z.inDaylightTime(new Date())){
        offset = offset + z.getDSTSavings();
    }
    int offsetHrs = offset / 1000 / 60 / 60;
    int offsetMins = offset / 1000 / 60 % 60;

    System.out.println("offset: " + offsetHrs);
    System.out.println("offset: " + offsetMins);

    c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
    c.add(Calendar.MINUTE, (-offsetMins));

    System.out.println("GMT Time: "+c.getTime());

52

实际上不是时间,但是它的表示形式可以更改。

SimpleDateFormat f = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));

在地球的任何一点上,时间都是相同的,但是根据位置的不同,我们对时间的理解可能会有所不同。


是的,不错且干净的解决方案。如果它不能有效地创建一个新的Date对象而不是仅仅获取Calendar实例,这让我感到担心?
Beemo

它将由JVM优化,并且HotSpot将执行可能的最有效的x86代码
Antonio

17

日历aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone(“ GMT”)); 然后,使用aGMTCalendar对象执行的所有操作都将在GMT时区完成,并且不会应用夏令时或固定的偏移量

错误!

Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
aGMTCalendar.getTime(); //or getTimeInMillis()

Calendar aNotGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));aNotGMTCalendar.getTime();

将在同一时间返回。同上

new Date(); //it's not GMT.

17

此代码显示当前时间UTC。

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


public class Test
{
    public static void main(final String[] args) throws ParseException
    {
        final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        f.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println(f.format(new Date()));
    }
}

结果

2013-10-26 14:37:48 UTC

14

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

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

7
仅需要减去偏移量?
tevch

c.add(Calendar.MILLISECOND, (-utcOffset))获取带有utc时区的日历
Shanavas M

10

乔恩·斯凯特(Jon Skeet)的回答似乎不正确。他说:

java.util.Date始终使用UTC。是什么让您认为这是当地时间?我怀疑问题在于您是通过使用本地时区的Calendar实例显示它,还是可能Date.toString()也使用本地时区的Calendar显示实例 。

但是,代码:

System.out.println(new java.util.Date().getHours() + " hours");

使用no Calendar和no 给出本地时间,而不是GMT(UTC小时)SimpleDateFormat

这就是为什么看起来有些不正确的原因。

汇总响应,代码:

System.out.println(Calendar.getInstance(TimeZone.getTimeZone("GMT"))
                           .get(Calendar.HOUR_OF_DAY) + " Hours");

显示的是格林尼治标准时间而非当地时间-请注意getTime.getHours()缺少该字段,因为这会创建一个Date()对象,该对象理论上将日期存储在格林尼治标准时间,但会以当地时区为准。


6
我以前没有看过这个答案,但是,如果您阅读了不赞成使用的Date.getHours()方法的文档,它会非常清楚:“返回的值是一个数字(0到23),代表一天中包含或以由该Date对象表示的即时时间,以当地时区为准。” (强调我的getHours()方法。)这是在本地时区内解释值的方法-它不是Date对象本身状态的一部分。
乔恩·斯基特

2
正如Jon Skeet正确指出的那样,java.util.Date对象没有时区。但令人困惑的方法toStringgetHours应用默认的时区,以它们的输出。因此,天真的程序员很容易被愚弄,因为日期似乎有一个时区,但实际上没有。
罗勒·布尔克

7

如果您希望Date对象的字段经过UTC调整,则可以使用Joda Time这样操作

import org.joda.time.DateTimeZone;
import java.util.Date;

...

Date local = new Date();
System.out.println("Local: " + local);
DateTimeZone zone = DateTimeZone.getDefault();
long utc = zone.convertLocalToUTC(local.getTime(), false);
System.out.println("UTC: " + new Date(utc));

1
你太辛苦了 Joda-Time可以在一行代码中完成此操作。看到对这个问题的回答。调用该.toDateTime方法并传递UTC时区的常量。
罗勒·布尔克

1
DateTime utcDate = new DateTime()。toDateTime(DateTimeZone.UTC)
Maciej Miklas

6

您可以使用:

Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

然后,使用aGMTCalendar对象执行的所有操作都将在GMT时区完成,并且不会应用夏令时或固定的偏移量。我认为先前的发布者是正确的,Date()对象始终返回GMT,直到您对将其转换为本地时区的date对象执行操作之前,它不会。


6
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));

请在您的答案中添加一些解释,它与其他许多答案有何不同?
akjoshi 2012年

这种方法获取时间是否取决于设备日历?
阿诺德·布朗

6

您可以直接使用

SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");

5

带有:

Calendar cal = Calendar.getInstance();

然后cal输入当前日期和时间。
您还可以通过以下方式获取时区的当前日期和时间:

Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));

您可以询问cal.get(Calendar.DATE);其他日历常量或其他日历常量。
日期和时间戳在Java中已弃用。日历类不是。


6
不赞成使用Date和Timestamp的某些方法和构造函数,但不赞成使用类本身。
Powerlord

5

以下是获取GMT时间戳记对象的另一种建议:

import java.sql.Timestamp;
import java.util.Calendar;

...

private static Timestamp getGMT() {
   Calendar cal = Calendar.getInstance();
   return new Timestamp(cal.getTimeInMillis()
                       -cal.get(Calendar.ZONE_OFFSET)
                       -cal.get(Calendar.DST_OFFSET));
}

5

这是获取String格式的GMT时间的另一种方法

String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z" ;
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String dateTimeString =  sdf.format(new Date());

5

这是我对toUTC的实现:

    public static Date toUTC(Date date){
    long datems = date.getTime();
    long timezoneoffset = TimeZone.getDefault().getOffset(datems);
    datems -= timezoneoffset;
    return new Date(datems);
}

可能有几种方法可以改善它,但对我有用。


3

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

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

3

只是为了让这个简单的,创建一个DateUTC你可以使用Calendar

Calendar.getInstance(TimeZone.getTimeZone("UTC"));

它将Calendar使用“ UTC” 构造一个新实例TimeZone

如果您需要Date该日历中的对象,则可以使用getTime()


5
对此调用getTime()会导致它丢失时区信息并返回本地时间。
RealCasually 2013年

3

以UTC转换当前日期时间:

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

DateTimeZone dateTimeZone = DateTimeZone.getDefault(); //Default Time Zone

DateTime currDateTime = new DateTime(); //Current DateTime

long utcTime = dateTimeZone.convertLocalToUTC(currDateTime .getMillis(), false);

String currTime = formatter.print(utcTime); //UTC time converted to string from long in format of formatter

currDateTime = formatter.parseDateTime(currTime); //Converted to DateTime in UTC

1
您在这里做太多工作。(a)默认情况下,您定义的格式化程序模式已内置在DateTime中;只需调用toStringDateTime即可获取该ISO 8601字符串模式。(b)太多代码无法在时区之间转换。只需调用“ toDateTime”并传递一个时区对象。像这样:myDateTime.toDateTime( DateTimeZone.UTC )。对于特定的时区,请基于专有名称 call 实例化并传递时区对象myDateTime.toDateTime( DateTimeZone.forID( "Asia/Tehran" ) )
罗勒·布尔克

2

这对我有用,返回格林尼治标准时间的时间戳!

    Date currDate;
    SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
    dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
    SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");

    long currTime = 0;
    try {

        currDate = dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
        currTime = currDate.getTime();
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

2

使用此类可以从在线NTP服务器获得正确的UTC时间:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


class NTP_UTC_Time
{
private static final String TAG = "SntpClient";

private static final int RECEIVE_TIME_OFFSET = 32;
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;

private static final int NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_VERSION = 3;

// Number of seconds between Jan 1, 1900 and Jan 1, 1970
// 70 years plus 17 leap days
private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;

private long mNtpTime;

public boolean requestTime(String host, int timeout) {
    try {
        DatagramSocket socket = new DatagramSocket();
        socket.setSoTimeout(timeout);
        InetAddress address = InetAddress.getByName(host);
        byte[] buffer = new byte[NTP_PACKET_SIZE];
        DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);

        buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);

        writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);

        socket.send(request);

        // read the response
        DatagramPacket response = new DatagramPacket(buffer, buffer.length);
        socket.receive(response);          
        socket.close();

        mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);            
    } catch (Exception e) {
      //  if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
        return false;
    }

    return true;
}


public long getNtpTime() {
    return mNtpTime;
}


/**
 * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
 */
private long read32(byte[] buffer, int offset) {
    byte b0 = buffer[offset];
    byte b1 = buffer[offset+1];
    byte b2 = buffer[offset+2];
    byte b3 = buffer[offset+3];

    // convert signed bytes to unsigned values
    int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
    int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
    int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
    int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);

    return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
}

/**
 * Reads the NTP time stamp at the given offset in the buffer and returns 
 * it as a system time (milliseconds since January 1, 1970).
 */    
private long readTimeStamp(byte[] buffer, int offset) {
    long seconds = read32(buffer, offset);
    long fraction = read32(buffer, offset + 4);
    return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);        
}

/**
 * Writes 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
 */    
private void writeTimeStamp(byte[] buffer, int offset) {        
    int ofs =  offset++;

    for (int i=ofs;i<(ofs+8);i++)
      buffer[i] = (byte)(0);             
}

}

并用于:

        long now = 0;

        NTP_UTC_Time client = new NTP_UTC_Time();

        if (client.requestTime("pool.ntp.org", 2000)) {              
          now = client.getNtpTime();
        }

如果您需要UTC时间“ now”作为DateTimeString,请使用以下函数:

private String get_UTC_Datetime_from_timestamp(long timeStamp){

    try{

        Calendar cal = Calendar.getInstance();
        TimeZone tz = cal.getTimeZone();

        int tzt = tz.getOffset(System.currentTimeMillis());

        timeStamp -= tzt;

        // DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
        DateFormat sdf = new SimpleDateFormat();
        Date netDate = (new Date(timeStamp));
        return sdf.format(netDate);
    }
    catch(Exception ex){
        return "";
     }
    } 

并用于:

String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);

用单行<br/> <pre> <code> Calendar utcTime = Calendar.getInstance()。add(Calendar.MILLISECOND,-time.getTimeZone()。getOffset(time.getTimeInMillis())); </ pre> / code>
Harun

1
是的,但这会调用本地设备时间,该时间可能会从用户手动更改为错误的DateTime
Ingo 2013年


1

简单地说。日历对象存储有关时区的信息,但是当您执行cal.getTime()时,时区信息将丢失。因此,对于时区转换,我建议使用DateFormat类...


1

这是我的实现:

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();    
}

1

如果要避免解析日期,而只需要GMT中的时间戳,则可以使用:

final Date gmt = new Timestamp(System.currentTimeMillis()
            - Calendar.getInstance().getTimeZone()
                    .getOffset(System.currentTimeMillis()));

0

如果您使用的是joda时间,并且想要以毫秒为单位的当前时间而不需要本地偏移,则可以使用以下命令:

long instant = DateTimeZone.UTC.getMillisKeepLocal(DateTimeZone.getDefault(), System.currentTimeMillis());

0
public class CurrentUtcDate 
{
    public static void main(String[] args) {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println("UTC Time is: " + dateFormat.format(date));
    }
}

输出:

UTC Time is: 22-01-2018 13:14:35

您可以根据需要更改日期格式。


1
请不要教年轻的孩子使用久违且臭名昭著的方法SimpleDateFormat。今天,我们java.time在现代Java日期和时间API中有了很多改进。您还提供了丹,安东尼奥和其他人尚未回答的内容吗?
Ole VV

2
(a)该答案如何在数十个现有答案中增加价值?(b)此处使用的麻烦类在多年前被现代的java.time类所取代。建议在2018年使用它们是不好的建议。
罗勒·布尔克

0

使用java.time包,并包含以下代码-

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

要么

LocalDateTime now2 = LocalDateTime.now( ZoneOffset.UTC );

取决于您的应用程序需求。


(A)如果使用偏移量(ZoneOffset)而不是时区(ZoneId),则OffsetDateTime它比更为合适ZonedDateTime。(B)LocalDateTime不应用于捕获当前时刻,因为它没有时区或UTC偏移量的概念。(C)其他先前存在的答案已经涵盖了此材料,并且做得更好。我不知道这个答案如何增加价值。
罗勒·布尔克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.