534

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

4

32 回答 32

437

java.util.Date没有特定的时区,尽管它的值最常被认为与 UTC 相关。是什么让你觉得是当地时间?

准确地说:a 中的值java.util.Date是自 Unix 纪元以来的毫秒数,该纪元发生在 UTC 时间 1970 年 1 月 1 日午夜。相同的纪元也可以在其他时区进行描述,但传统的描述是用 UTC 来描述的。由于自固定纪元以来的毫秒数,因此java.util.Date无论本地时区如何,在任何特定时刻,全球范围内的值都是相同的。

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

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

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

于 2008-11-21T13:04:32.483 回答
436
于 2013-10-28T10:14:46.423 回答
279
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()) );
于 2010-03-27T07:08:23.167 回答
91

这肯定会返回 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;
}
于 2011-07-14T18:06:20.460 回答
68
    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());
于 2010-03-16T11:14:00.263 回答
56

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

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

地球上任何一点的时间都是相同的,但我们对时间的感知可能会因位置而异。

于 2010-11-08T14:23:46.477 回答
18

日历 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.
于 2010-04-06T14:28:34.103 回答
17

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

Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);  
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;
于 2013-05-16T19:35:11.493 回答
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
于 2013-10-26T14:39:47.783 回答
10

这是Jon Skeet 的回答中似乎不正确的内容。他说:

java.util.Date始终采用 UTC。是什么让你觉得是当地时间?我怀疑问题是您通过使用本地时区的日历实例显示它,或者可能使用 Date.toString()也使用本地时区的日历实例。

但是,代码:

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

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

这就是为什么似乎有些不正确的原因。

将响应放在一起,代码:

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

显示格林威治标准时间而不是当地小时——请注意,getTime.getHours()这将创建一个Date()对象,该对象理论上将日期存储在格林威治标准时间,但会返回当地时区的小时。

于 2012-05-22T18:01:10.167 回答
7

如果您想要一个字段为 UTC 调整的 Date 对象,您可以使用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));
于 2012-05-04T10:51:55.123 回答
6

您可以使用:

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

然后使用 aGMTCalendar 对象执行的所有操作都将使用 GMT 时区完成,并且不会应用夏令时或固定偏移量。我认为之前的海报是正确的,Date() 对象总是返回一个 GMT,直到你对日期对象做一些事情,它才会被转换为本地时区。

于 2010-01-26T16:32:00.830 回答
6
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));
于 2010-12-21T11:36:14.037 回答
6

你可以直接使用这个

SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");
于 2012-04-17T06:39:27.163 回答
6

这是我对 toUTC 的实现:

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

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

于 2016-08-31T15:10:16.523 回答
5

这是获取 GMT Timestamp 对象的另一个建议:

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));
}
于 2012-05-09T10:34:25.493 回答
5

这是另一种以字符串格式获取 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());
于 2012-10-01T03:48:52.807 回答
4

和:

Calendar cal = Calendar.getInstance();

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

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

您可以向cal.get(Calendar.DATE);其他日历常量询问其他详细信息。
Java 中不推荐使用日期和时间戳。日历类不是。

于 2008-11-21T13:10:06.107 回答
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
于 2011-10-09T00:51:30.800 回答
3

Date只是为了让这更简单,创建一个UTC你可以使用Calendar

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

它将构造一个Calendar使用 "UTC"的新实例TimeZone

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

于 2012-05-17T13:04:37.097 回答
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
于 2014-01-08T13:08:38.287 回答
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();
    }
于 2013-03-25T12:46:16.860 回答
2
public static void main(String args[]){
    LocalDate date=LocalDate.now();  
    System.out.println("Current date = "+date);
}
于 2016-10-19T10:31:42.390 回答
1

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

于 2012-12-05T08:21:38.047 回答
1

使用此类从在线 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 时间“现在”作为 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);
于 2013-11-01T21:49:57.253 回答
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();    
}
于 2014-05-27T05:52:42.537 回答
1

如果您想避免解析日期并且只想要 GMT 的时间戳,您可以使用:

final Date gmt = new Timestamp(System.currentTimeMillis()
            - Calendar.getInstance().getTimeZone()
                    .getOffset(System.currentTimeMillis()));
于 2015-08-11T06:55:04.643 回答
1
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

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

于 2018-07-04T03:24:38.183 回答
0

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

long instant = DateTimeZone.UTC.getMillisKeepLocal(DateTimeZone.getDefault(), System.currentTimeMillis());
于 2015-07-08T10:18:30.217 回答
0

UTC 中的当前日期

Instant.now().toString().replaceAll("T.*", "");
于 2019-03-04T07:52:52.790 回答
0

当我需要输出一个 Date 对象时,我就是这样做的,这通常是当您需要将 Date 保存在 SQL 数据库中并且我希望它采用 UTC 时的情况。我只是减去本地时区的偏移时间。

    ZonedDateTime now = ZonedDateTime.now();
    Date nowUTC = new Date(1000 * (now.toEpochSecond() - now.getOffset().getTotalSeconds()));

--UPDATE Basil 建议以更清洁的方式获得相同的结果

    Date nowUTC = Date.from(ZonedDateTime.now().toInstant());

但是在非UTC java系统环境中测试后,我发现结果不一样。使用 Basil 的代码,日期仍在本地区域

于 2022-01-20T08:42:49.783 回答
-1

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

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

或者

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

取决于您的应用需求。

于 2018-11-01T22:47:26.393 回答