Làm cách nào tôi có thể nhận được ngày và giờ hiện tại bằng UTC hoặc GMT bằng Java?


479

Khi tôi tạo một Dateđối tượng mới , nó được khởi tạo cho thời gian hiện tại nhưng theo múi giờ địa phương. Làm cách nào tôi có thể nhận được ngày giờ hiện tại trong GMT?


Tôi biết các loại chủ đề này hoàn toàn được thảo luận, nhưng tôi thấy gói commons-lang thực sự xử lý tốt các vấn đề java phổ biến này. commons.apache.org/lang/api-2.5/org/apache/commons/lang/time Kiểm tra các gói khác nhau mà họ có.

Bạn muốn giờ nào ở địa phương, và chính xác là gì. Hầu hết các múi giờ được xác định liên quan đến UTC với độ lệch cố định được đo bằng SI giây, nhưng mối quan hệ của GMT dựa trên quan sát mặt trời và chiều dài biến (hơi) thứ hai phức tạp hơn. Hai cái khác nhau tới 0,9 giây.
mc0e

1
A Datekhông giữ múi giờ, vì vậy "nhưng trong múi giờ địa phương thì không đúng (hoặc không chính xác nhất). Xem tất cả về java.util.Date .
Ole VV

Câu trả lời:


409

java.util.Datekhông có múi giờ cụ thể, mặc dù giá trị của nó thường được cho là liên quan đến UTC. Điều gì khiến bạn nghĩ rằng đó là giờ địa phương?

Nói chính xác: giá trị trong a java.util.Datelà số mili giây kể từ thời kỳ Unix, xảy ra vào nửa đêm ngày 1 tháng 1 năm 1970, UTC. Kỷ nguyên tương tự cũng có thể được mô tả trong các múi giờ khác, nhưng mô tả truyền thống là về UTC. Vì đó là một số mili giây kể từ một kỷ nguyên cố định, giá trị bên trong java.util.Datelà giống nhau trên toàn thế giới tại bất kỳ thời điểm cụ thể nào, bất kể múi giờ địa phương.

Tôi nghi ngờ vấn đề là bạn đang hiển thị nó thông qua một phiên bản Lịch sử dụng múi giờ địa phương hoặc có thể sử dụng Date.toString()cũng sử dụng múi giờ địa phương hoặc một SimpleDateFormattrường hợp, theo mặc định, cũng sử dụng múi giờ cục bộ.

Nếu đây không phải là vấn đề, xin vui lòng gửi một số mã mẫu.

Tuy nhiên, tôi sẽ khuyên bạn nên sử dụng Joda-Time , điều này cung cấp API rõ ràng hơn nhiều.


5
Sau đó, đó có thể là một vấn đề trình điều khiển. Bạn có thể cần đặt kết nối của mình thành UTC hoặc đại loại như thế. Tôi đã thấy các vấn đề như thế này trước đây, nhưng vấn đề không nằm ở java.util.Date.
Jon Skeet

13
Hành vi, theo stackoverflow.com/questions/4123534/ , trình điều khiển JDBC của MySQL chuyển đổi một java.util.Timestamp(hoặc java.util.Date) nhất định thành múi giờ của máy chủ.
Derek Mahar

5
@Ông. Cát: Làm thế nào để bạn xác định điều đó? Có phải bằng văn bản System.out.println(new Date())? Nếu vậy, bạn nên lưu ý rằng đó là toString()phương pháp đang áp dụng múi giờ ở đó ... nếu không phải vậy, vui lòng cung cấp thêm chi tiết.
Jon Skeet

8
@KanagaveluSugumar: toString()luôn sử dụng múi giờ mặc định. date.getTime()chắc chắn trả về mili giây kể từ thời kỳ Unix, trong UTC. Chính xác nhất để nói rằng Datebản thân nó hoàn toàn không có múi giờ - đó chỉ là một khoảnh khắc tức thời, có thể được xem xét trong nhiều múi giờ. Nhưng khi bạn tạo một thể hiện, nó không phụ thuộc vào múi giờ của bạn.
Jon Skeet

6
@Jemenake: Thật ra điều đó đã không xảy ra khi đó là nửa đêm ở Greenwich, vì Vương quốc Anh đang ở trên UTC + 1 vào thời điểm đó. Chỉ là một trong những bit lẻ của lịch sử. Nhưng tôi đưa ra quan điểm của bạn - tốt hơn hết là nói "Ngày mới (). GetTime () trả về mili giây kể từ thời kỳ Unix, lúc nửa đêm vào đầu ngày 1 tháng 1 năm 1970, UTC". Vì vậy, UTC là một phần của việc ghim xuống kỷ nguyên đến một thời điểm cụ thể, không phải là một phần của kết quả.
Jon Skeet

324

tl; dr

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

Tạo một chuỗi để biểu thị giá trị đó:

Instant.now().toString()  

2016-09-13T23: 30: 52.123Z

Chi tiết

Như câu trả lời đúng bởi Jon Skeet nói, một đối tượng java.util.Date có không múi giờ . Nhưng việc toStringtriển khai nó áp dụng múi giờ mặc định của JVM khi tạo biểu diễn Chuỗi của giá trị thời gian ngày đó. Khó hiểu với lập trình viên ngây thơ, một Ngày dường như có múi giờ nhưng không.

Các java.util.Date, j.u.Calendarjava.text.SimpleDateFormatcác lớp học kèm với Java nổi tiếng là phiền hà. Tránh chúng. Thay vào đó, hãy sử dụng một trong những thư viện thời gian có thẩm quyền này:

java.time (Java 8)

Java 8 mang đến một gói java.time. * Mới tuyệt vời để thay thế các lớp java.util.Date/CalWiki cũ.

Có được thời gian hiện tại trong UTC / GMT là một trò chơi đơn giản

Instant instant = Instant.now();

InstantLớp đó là khối xây dựng cơ bản trong java.time, đại diện cho một khoảnh khắc trên dòng thời gian trong UTC với độ phân giải nano giây .

Trong Java 8, khoảnh khắc hiện tại được ghi lại chỉ với độ phân giải lên đến mili giây. Java 9 mang đến một triển khai mới để Clockghi lại khoảnh khắc hiện tại với khả năng đầy đủ nano giây của lớp này, tùy thuộc vào khả năng của phần cứng đồng hồ của máy chủ của bạn.

Đó là toStringphương pháp tạo ra một chuỗi đại diện giá trị của nó sử dụng một định dạng cụ thể theo tiêu chuẩn ISO 8601 . Định dạng đó tạo ra các chữ số 0, ba, sáu hoặc chín chữ số ( mili giây , micro giây hoặc nano giây ) khi cần để biểu thị phân số của giây.

Nếu bạn muốn định dạng linh hoạt hơn hoặc các tính năng bổ sung khác, thì hãy áp dụng offset từ UTC bằng 0, cho chính UTC ( ZoneOffset.UTCkhông đổi ) để có được a OffsetDateTime.

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

Kết xuất giao diện điều khiển

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

Khi chạy đào

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

Bảng các loại thời gian trong Java, cả hiện đại và di sản.


Giới thiệu về java.time

Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date, Calendar, & SimpleDateFormat.

Để tìm hiểu thêm, xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp.

Nơi để có được các lớp java.time?

Bảng mà thư viện java.time sẽ sử dụng với phiên bản Java hoặc Android nào

Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho các bổ sung có thể trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval, YearWeek, YearQuarter, và nhiều hơn nữa .


Joda-Thời gian

CẬP NHẬT: Dự án Joda-Time , hiện ở chế độ bảo trì , khuyên chuyển sang các lớp java.time .

Sử dụng thư viện miễn phí mã nguồn mở của bên thứ ba Joda , bạn có thể có được thời gian ngày hiện tại chỉ trong một dòng mã.

Joda-Time đã truyền cảm hứng cho các lớp java.time. * Mới trong Java 8, nhưng có kiến ​​trúc khác. Bạn có thể sử dụng Joda-Time trong các phiên bản Java cũ hơn. Joda-Time tiếp tục hoạt động trong Java 8 và tiếp tục được duy trì tích cực (kể từ năm 2014). Tuy nhiên, nhóm Joda-Time không khuyên di chuyển sang java.time.

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

Mã ví dụ chi tiết hơn (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 );

Kết xuất giao diện điều khiển

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

Khi chạy đào

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

Để biết thêm ví dụ mã thực hiện công việc múi giờ, hãy xem câu trả lời của tôi cho một câu hỏi tương tự.

Múi giờ

Tôi khuyên bạn luôn luôn chỉ định múi giờ thay vì dựa hoàn toàn vào múi giờ mặc định hiện tại của JVM (có thể thay đổi bất cứ lúc nào!). Sự phụ thuộc như vậy dường như là một nguyên nhân phổ biến của sự nhầm lẫn và lỗi trong công việc thời gian.

Khi gọi now()vượt qua múi giờ mong muốn / dự kiến ​​sẽ được chỉ định. Sử dụng DateTimeZonelớp học.

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

Lớp đó giữ một hằng số cho múi giờ UTC .

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

Nếu bạn thực sự muốn sử dụng múi giờ mặc định hiện tại của JVM, hãy thực hiện một cuộc gọi rõ ràng để mã của bạn tự ghi lại.

DateTimeZone zoneDefault = DateTimeZone.getDefault();

ISO 8601

Đọc về các định dạng ISO 8601 . Cả java.time và Joda-Time đều sử dụng các định dạng hợp lý của tiêu chuẩn đó làm mặc định cho cả phân tích cú pháp và tạo chuỗi.


Trên thực tế, java.util.Date không có một múi giờ, chôn sâu dưới lớp mã nguồn. Đối với hầu hết các mục đích thực tế, múi giờ đó bị bỏ qua. Vì vậy, như tốc ký, chúng tôi nói java.util.Date không có múi giờ. Hơn nữa, múi giờ bị chôn vùi đó không phải là múi giờ được sử dụng bởi toStringphương pháp của Date ; phương thức đó sử dụng múi giờ mặc định hiện tại của JVM. Tất cả lý do nhiều hơn để tránh lớp khó hiểu này và gắn bó với Joda-Time và java.time.


2
DateTime.now().toDateTime(DateTimeZone.UTC)là những gì tôi đang tìm kiếm! Cảm ơn!
Managearm

1
@Managarm Bạn có thể rút ngắn điều đó thành: DateTime nowUtc = DateTime.now ( DateTimeZone.UTC ) ;
Basil Bourque

Cách lấy cái này với Pure Java 8 2014-01-21T15:34:29.933-08:00trong ví dụ bạn đã sử dụngnew org.joda.time.DateTime()
GOXR3PLUS

1
@ GOXR3PLUS ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ).truncatedTo( ChronoUnit.MILLIS ).toOffsetDateTime().toString() Chúng tôi có được thời điểm hiện tại cho một múi giờ được chỉ định. Tiếp theo, tắt bất kỳ micros / nanos. Sau đó, chúng tôi chuyển đổi thành chỉ có một phần bù từ UTC (số giờ-phút-giây) thay vì múi giờ đầy đủ (lịch sử của quá khứ, hiện tại và những thay đổi trong tương lai được sử dụng bởi những người của a khu vực cụ thể). Cuối cùng, chúng tôi tạo văn bản đại diện cho giá trị theo OffsetDateTimeđịnh dạng ISO 8601 tiêu chuẩn được sử dụng theo mặc định trong toStringphương thức của nó .
Basil Bourque

Cảm ơn bạn đã đưa ra lời giải thích chi tiết này, cũng +1 cho các hỗ trợ Android :) @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
Tại sao bạn phân tích cú pháp với dateFormatLocal sau khi sử dụng định dạng dateFormatGmt ... không có nghĩa gì khi đọc nó. Tôi chắc chắn rằng nó hoạt động, nhưng chỉ cần tự hỏi?
MindWire

2
setTimeZone đã làm điều đó (tôi đoán bạn cũng có thể sử dụng getTimeZone ("UTC") giống như GMT?)
rogerdpack 6/213

6
nhưng thời gian phụ thuộc vào thời gian thiết lập thiết bị. Nếu người dùng đặt sai thời gian trên thiết bị của mình thì bạn sẽ nhận được UTC sai. Hãy sửa lỗi cho tôi nếu tôi sai
Basavaraj Hampali

@BasavarajHampali nhưng trong thế giới ngày nay hầu hết các thiết bị được kết nối với internet điều chỉnh thời gian không chính xác
Akshat Agarwal

3
Không có sự khác biệt về thời gian giữa Giờ quốc tế phối hợp (UTC) và Giờ trung bình Greenwich (GMT)
slott

86

Điều này chắc chắn trả về thời gian UTC: dưới dạng các đối tượng Chuỗi và Ngày!

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

Trong câu trả lời của mình, tôi đã quên chỉ ra cách DATEFORMAT được định nghĩa: static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
Ai đó ở đâu đó vào

21
Vui lòng tránh bắt đầu tên phương thức bằng chữ hoa trong Java. Xem các quy ước mã hóa Java cho các tên phương thức.
Florian Schrofner

2
Như được chuyển hướng đến câu trả lời này, Gọi new Date()sẽ không bao giờ trả lại thời gian UTC chính xác, nếu thời gian của thiết bị sai.
Sanoop

phương pháp này có nhận được thời gian phụ thuộc vào lịch thiết bị không?
Arnold Brown

Một điều cần lưu ý. Bất kỳ giải pháp nào cần lấy Ngày hoặc Dấu thời gian trong UTC, có vẻ như chìa khóa là không sử dụng lại SimpleDateFormat, mà sử dụng một để lấy UTC thành chuỗi, sau đó tạo một UTC khác khi chuyển đổi chuỗi thành Ngày hoặc đối tượng dấu thời gian. Tôi nhận thấy rằng nếu bạn cố gắng sử dụng lại SimpleDateFormat tương tự thì đối tượng Ngày / Dấu thời gian kết quả sẽ trở lại múi giờ địa phương thay vì UTC.
Brian Bắt đầu

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

Trên thực tế không phải là thời gian, nhưng đại diện của nó có thể được thay đổi.

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

Thời gian là như nhau ở bất kỳ điểm nào trên Trái đất, nhưng nhận thức của chúng ta về thời gian có thể khác nhau tùy theo vị trí.


Yep, giải pháp tốt đẹp và sạch sẽ. Nó chỉ làm tôi lo lắng, nếu nó không hiệu quả để tạo một đối tượng Date mới thay vì chỉ lấy phiên bản Lịch?
Beemo

Nó sẽ được tối ưu hóa bởi JVM và HotSpot sẽ thực thi mã x86 hiệu quả nhất có thể
Antonio

17

Lịch aGMTCalWiki = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); Sau đó, tất cả các hoạt động được thực hiện bằng cách sử dụng đối tượng aGMTCalWiki sẽ được thực hiện với múi giờ GMT và sẽ không áp dụng thời gian tiết kiệm ánh sáng ban ngày hoặc bù đắp cố định

Sai lầm!

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

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

sẽ trở lại cùng một lúc. Idem cho

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

17

Mã này in UTC thời gian hiện tại.

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

Kết quả

2013-10-26 14:37:48 UTC

14

Điều này hoạt động để có được UTC mili giây trong Android.

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

7
chỉ cần bạn trừ đi phần bù?
tevch

c.add(Calendar.MILLISECOND, (-utcOffset))để lấy Lịch với múi giờ utc
Shanavas M

10

Đây là những gì dường như không chính xác trong câu trả lời của Jon Skeet . Anh nói:

java.util.Dateluôn ở trong UTC. Điều gì khiến bạn nghĩ rằng đó là giờ địa phương? Tôi nghi ngờ vấn đề là bạn đang hiển thị nó thông qua một phiên bản Lịch sử dụng múi giờ địa phương hoặc có thể sử Date.toString()dụng cả múi giờ địa phương.

Tuy nhiên, mã:

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

cung cấp giờ địa phương, không phải GMT (giờ UTC), sử dụng không Calendarvà không có gì SimpleDateFormatcả.

Đó là lý do tại sao dường như một cái gì đó là không chính xác.

Kết hợp các câu trả lời, mã:

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

hiển thị giờ GMT thay vì giờ địa phương - lưu ý getTime.getHours()bị thiếu vì điều đó sẽ tạo ra một Date()đối tượng, theo lý thuyết sẽ lưu trữ ngày trong GMT, nhưng trả lại giờ trong múi giờ địa phương.


6
Tôi đã không thấy câu trả lời này trước đây, nhưng nếu bạn đọc tài liệu về Date.getHours()phương pháp không dùng nữa , thì nó rất rõ ràng: "Giá trị được trả về là một số (0 đến 23) đại diện cho giờ trong ngày có hoặc bắt đầu bằng tức thời theo thời gian được đại diện bởi đối tượng Ngày này, như được diễn giải theo múi giờ địa phương . " (Nhấn mạnh của tôi.) Đó là getHours()phương pháp diễn giải giá trị trong múi giờ địa phương - nó không phải là một phần của trạng thái của Datechính đối tượng.
Jon Skeet

2
Như Jon Skeet đã nêu chính xác, một đối tượng java.util.Date không có múi giờ . Nhưng thật khó hiểu, các phương thức toStringgetHoursáp dụng múi giờ mặc định cho đầu ra của chúng. Vì vậy, các lập trình viên ngây thơ rất dễ bị lừa vì có vẻ như Date có múi giờ nhưng thực tế thì không.
Basil Bourque

7

Nếu bạn muốn một đối tượng Date với các trường được điều chỉnh cho UTC, bạn có thể làm điều đó như thế này với 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
Bạn đang làm việc quá sức. Joda-Time có thể làm điều này trong một dòng mã. Xem câu trả lời của riêng tôi về câu hỏi này. Gọi .toDateTimephương thức và truyền hằng số cho múi giờ UTC.
Basil Bourque

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

6

Bạn có thể dùng:

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

Sau đó, tất cả các hoạt động được thực hiện bằng cách sử dụng đối tượng aGMTCalWiki sẽ được thực hiện với múi giờ GMT và sẽ không áp dụng thời gian tiết kiệm ánh sáng ban ngày hoặc bù đắp cố định. Tôi nghĩ rằng áp phích trước là chính xác rằng đối tượng Date () luôn trả về GMT không phải cho đến khi bạn đi làm gì đó với đối tượng ngày mà nó được chuyển đổi thành múi giờ địa phương.


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

Vui lòng thêm một số lời giải thích cho câu trả lời của bạn, nó khác với rất nhiều câu trả lời khác như thế nào?
akjoshi

phương pháp này có nhận được thời gian phụ thuộc vào lịch thiết bị không?
Arnold Brown

6

Bạn có thể trực tiếp sử dụng

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

5

Với:

Calendar cal = Calendar.getInstance();

Sau đó calcó ngày giờ hiện tại.
Bạn cũng có thể nhận được Ngày và Giờ hiện tại cho múi giờ với:

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

Bạn có thể hỏi cal.get(Calendar.DATE);hoặc lịch khác liên tục về các chi tiết khác.
Ngày và Dấu thời gian không được dùng trong Java. Lịch học không phải vậy.


6
Một số phương thức và hàm tạo của Date và Timestamp không được dùng nữa, nhưng bản thân các lớp thì không.
Powerlord

5

Đây là một đề xuất khác để có được một đối tượng Dấu thời gian 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

Đây là một cách khác để có được thời gian GMT ở định dạng Chuỗi

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

Đây là cách triển khai toUTC của tôi:

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

Có lẽ có nhiều cách để cải thiện nó, nhưng nó hiệu quả với tôi.


3

Mã mẫu để hiển thị thời gian hệ thống theo múi giờ cụ thể và định dạng cụ thể.

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

}

Đầu ra

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

Chỉ cần làm cho đơn giản hơn, để tạo một Datetrong UTCbạn có thể sử dụng Calendar:

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

Nó sẽ xây dựng một thể hiện mới để Calendarsử dụng "UTC" TimeZone.

Nếu bạn cần một Dateđối tượng từ lịch đó, bạn có thể sử dụng getTime().


5
Gọi getTime () trên này khiến nó mất thông tin múi giờ và trả về giờ địa phương.
RealCasual

3

Chuyển đổi DateTime hiện tại trong 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
Bạn đang làm quá nhiều việc ở đây. (a) Trình định dạng bộ định dạng mà bạn xác định đã được tích hợp vào DateTime theo mặc định; chỉ cần gọi toStringvào DateTime để lấy mẫu chuỗi ISO 8601 đó . (b) Cách quá nhiều mã để chuyển đổi giữa các múi giờ. Chỉ cần gọi "toDateTime" và truyền đối tượng múi giờ. Như thế này : myDateTime.toDateTime( DateTimeZone.UTC ). Đối với một múi giờ cụ thể, khởi tạo và vượt qua một đối tượng múi giờ dựa trên một tên thích hợp , gọi myDateTime.toDateTime( DateTimeZone.forID( "Asia/Tehran" ) ).
Basil Bourque

2

Điều này làm việc cho tôi, trả về dấu thời gian trong GMT!

    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

Sử dụng Lớp này để nhận được Thời gian UTC đúng từ Máy chủ NTP trực tuyến:

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

}

Và sử dụng nó với:

        long now = 0;

        NTP_UTC_Time client = new NTP_UTC_Time();

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

Nếu bạn cần UTC Time "ngay bây giờ" là chức năng sử dụng 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 "";
     }
    } 

và sử dụng nó với:

String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);

Trong một dòng duy nhất <br/> <pre> <code> Lịch utcTime = Lịch.getInstance (). / code>
Harun

1
Có, nhưng điều này gọi Giờ thiết bị cục bộ, có thể thay đổi hướng dẫn sử dụng từ người dùng thành DateTime sai
Ingo

2
public static void main(String args[]){
    LocalDate date=LocalDate.now();  
    System.out.println("Current date = "+date);
}

1

Nói một cách đơn giản. Một đối tượng lịch lưu trữ thông tin về múi giờ nhưng khi bạn thực hiện cal.getTime () thì thông tin múi giờ sẽ bị mất. Vì vậy, đối với chuyển đổi múi giờ, tôi sẽ khuyên bạn nên sử dụng các lớp DateFormat ...


1

đây là triển khai của tôi:

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

Nếu bạn muốn tránh phân tích ngày và chỉ muốn dấu thời gian trong GMT, bạn có thể sử dụng:

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

0

Nếu bạn đang sử dụng thời gian joda và muốn thời gian hiện tại tính bằng mili giây mà không cần bù cục bộ, bạn có thể sử dụng điều này:

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

Đầu ra:

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

Bạn có thể thay đổi định dạng ngày nếu cần.


1
Xin đừng dạy những người trẻ tuổi sử dụng những thứ lỗi thời và nổi tiếng là rắc rối SimpleDateFormat. Ngày nay chúng ta có java.timeAPI ngày và giờ hiện đại tốt hơn rất nhiều . Ngoài ra, bạn đang cung cấp những gì chưa có trong câu trả lời của Dan, Antonio và những người khác?
Ole VV

2
(a) Làm thế nào để Câu trả lời này thêm giá trị qua hàng tá Câu trả lời hiện có? (b) Các lớp rắc rối được sử dụng ở đây đã được thay thế bởi các lớp java.time hiện đại . Đề xuất sử dụng của họ trong năm 2018 là lời khuyên kém.
Basil Bourque

0

Sử dụng gói java.time và bao gồm mã bên dưới-

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

hoặc là

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

tùy thuộc vào nhu cầu ứng dụng của bạn.


(A) Nếu sử dụng offset ( ZoneOffset) thay vì múi giờ ( ZoneId), thì OffsetDateTimephù hợp hơn ZonedDateTime. (B) LocalDateTimekhông nên được sử dụng để ghi lại khoảnh khắc hiện tại vì nó không có khái niệm về múi giờ hoặc offset-từ-UTC. (C) Các câu trả lời có sẵn khác đã đề cập đến tài liệu này và thực hiện công việc tốt hơn. Tôi không thấy câu trả lời này làm tăng giá trị như thế nào.
Basil Bourque
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.