Java'da UTC veya GMT'de geçerli tarih ve saati nasıl alabilirim?


479

Yeni bir Datenesne oluşturduğumda , geçerli saate ancak yerel saat diliminde başlatılır. GMT'de geçerli tarih ve saati nasıl alabilirim?


Bu tür konuların tamamen tartışıldığını biliyorum, ancak commons-lang paketinin bu yaygın java sorunlarını gerçekten iyi işlediğini buldum. commons.apache.org/lang/api-2.5/org/apache/commons/lang/time Sahip oldukları çeşitli paketlere göz atın.

Hangi yerel saati ve hangi hassasiyeti istiyorsunuz? Çoğu zaman dilimi UTC'ye göre SI saniyelerinde ölçülen sabit bir ofset ile tanımlanır , ancak güneş gözlemine ve (hafif) değişken uzunluktaki bir saniyeye dayanan GMT'nin ilişkisi daha karmaşıktır. İkisi 0.9 saniyeye kadar farklılık gösterir.
mc0e

1
A Datebir saat dilimi içermiyor, bu yüzden "ama yerel saat diliminde" doğru değil (veya en iyi ihtimalle yanlış). Bkz . Java.util.Date hakkında her şey
Ole VV

Yanıtlar:


409

java.util.Datedeğeri UTC ile ilişkili olarak düşünülmesine rağmen belirli bir saat dilimi yoktur. Sizi yerel saatte düşündüren nedir?

Kesin olmak gerekirse: a içindeki değer java.util.Date, 1 Ocak 1970 gece yarısı UTC'de gerçekleşen Unix döneminden bu yana geçen milisaniye sayısıdır. Aynı çağ diğer zaman dilimlerinde de açıklanabilir, ancak geleneksel açıklama UTC cinsindendir. Sabit bir çağdan bu yana geçen milisaniye sayısı nedeniyle, içerideki değer java.util.Date, yerel saat diliminden bağımsız olarak herhangi bir anda dünyanın her yerinde aynıdır.

Sorunun, yerel saat dilimini kullanan veya muhtemelen yerel saat dilimini de kullanan bir Takvim örneği Date.toString()veya SimpleDateFormatvarsayılan olarak yerel saat dilimini kullanan bir örnek aracılığıyla görüntülediğinizden şüpheleniyorum .

Sorun bu değilse, lütfen bazı örnek kodlar gönderin.

Bununla birlikte, daha net bir API sunan Joda-Time'ı yine de kullanmanızı tavsiye ederim .


5
O zaman bu muhtemelen bir sürücü sorunudur. Bağlantınızı UTC'ye veya bunun gibi bir şeye ayarlamanız gerekebilir. Daha önce böyle sorunlar gördüm, ama sorun java.util.Date'de değil.
Jon Skeet

13
Yığın, stackoverflow.com/questions/4123534/… 'a göre , MySQL JDBC sürücüsü belirli bir java.util.Timestamp(veya java.util.Date) sunucuyu saat dilimine dönüştürür.
Derek Mahar

5
@Bay. Cat: Bunu nasıl belirliyorsunuz? Yazarak System.out.println(new Date())mı? Eğer öyleyse, toString()oradaki saat dilimini uygulayan yöntem olduğunu bilmelisiniz ... değilse, lütfen daha fazla ayrıntı verin.
Jon Skeet

8
@KanagaveluSugumar: toString()her zaman varsayılan saat dilimini kullanır. date.getTime()Unix döneminden beri UTC cinsinden kesinlikle milisaniye döndürür. DateKendisinin hiç bir zaman dilimine sahip olmadığını söylemek en doğrudur - birden fazla zaman diliminde görülebilen sadece bir andır. Ancak bir örnek oluşturduğunuzda , saat diliminize bağlı değildir .
Jon Skeet

6
@Jemenake: Aslında Greenwich'te gece yarısı olduğu zaman olmadı, çünkü İngiltere o sırada UTC + 1'deydi. Tarihin tuhaf parçalarından sadece biri. Ama dikkatinizi çekiyorum - "new Date (). GetTime (), 1 Ocak 1970, UTC'nin gece yarısı olan Unix döneminden bu yana milisaniyeyi döndürüyor" demek daha iyidir. Dolayısıyla UTC, çağın sonucun bir parçası değil, belirli bir anı sabitlemenin bir parçasıdır.
Jon Skeet

324

tl; Dr.

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

Bu değeri temsil etmek için bir Dize oluşturun:

Instant.now().toString()  

2016-09-13T23: 30: 52.123Z

ayrıntılar

As Jon Skeet tarafından doğru cevap belirtildiği, bir java.util.Date nesne vardır hiçbir zaman dilimini . Ancak toStringuygulaması, o tarih-saat değerinin String temsilini oluştururken JVM'nin varsayılan saat dilimini uygular. Naif programcıya kafa karıştırıcı bir şekilde, bir Tarihin saat dilimi var gibi görünüyor , ancak yok.

java.util.Date, j.u.CalendarVe java.text.SimpleDateFormatJava ile birlikte sınıfları herkesin bildiği zahmetli bulunmaktadır. Onlardan kaçının. Bunun yerine, şu yetkili tarih-saat kitaplıklarından birini kullanın:

java.time (Java 8)

Java 8 , eski java.util.Date/Calendar sınıflarını tamamlamak için mükemmel bir yeni java.time. * Paketi getiriyor .

UTC / GMT'de şimdiki zamanı almak basit bir astar…

Instant instant = Instant.now();

Yani Instantsınıf içinde zaman çizelgesi üzerinde bir an temsil eden java.time temel yapı taşı olan UTC çözünürlüğe sahip nanosaniye .

Java 8'de geçerli an yalnızca milisaniyeye kadar çözünürlükte yakalanır. Java 9 yeni bir uygulamasıdır getiriyor ait Clockhost bilgisayarın saati donanım yeteneği bağlı olarak, bu sınıfın tam nanosaniye yeteneği up yakalamaları güncel anı.

'S toStringbir yöntem kullanarak değer bir String temsilini oluşturur belirli bir ISO 8601 biçimi . Bu biçim , saniye bölümünü temsil etmek için gerektiği şekilde sıfır, üç, altı veya dokuz basamaklı basamaklar ( milisaniye , mikrosaniye veya nanosaniye ) verir.

Daha esnek biçimlendirme veya diğer ek özellikler istiyorsanız, UTC'nin kendisinin ( ZoneOffset.UTCsabit ) bir a olması için UTC'den sıfırdan bir ofset uygulayın OffsetDateTime.

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

Konsola dökümü…

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

Çalıştırıldığında…

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

Java'da hem modern hem de eski tarih-saat türleri tablosu.


Hakkında java.time

Java.time çerçevesi daha sonra Java 8 ve yerleşiktir. Bu sınıflar zahmetli eski yerini mirası gibi tarih-saat sınıfları java.util.Date, Calendar& SimpleDateFormat.

Daha fazla bilgi için Oracle Eğiticisine bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310'dur .

Artık bakım modunda olan Joda-Time projesi java.time sınıflarına geçişi tavsiye ediyor .

Sen değiştirebilir java.time sizin veritabanı ile doğrudan nesneleri. JDBC 4.2 veya sonraki bir sürümüyle uyumlu bir JDBC sürücüsü kullanın . Dizeye gerek yok, sınıflara gerek yok .java.sql.*

Java.time sınıflarını nereden edinebilirsiniz?

Hangi Java veya Android sürümüyle kullanılacak java.time kütüphanesinin tablosu

ThreeTen-Ekstra proje ek sınıfları ile java.time uzanır. Bu proje, java.time'a gelecekteki olası eklemeler için bir kanıt zeminidir. Burada bazı yararlı sınıfları gibi bulabilir Interval, YearWeek, YearQuarter, ve daha .


Joda-Time

GÜNCELLEME: Artık bakım modunda olan Joda-Time projesi java.time sınıflarına geçişi tavsiye ediyor .

Kullanılması Joda-Time serbest-of-maliyet 3. taraf açık kaynak kütüphane, kod sadece bir satırda geçerli tarih-zaman dönebilirsiniz.

Joda-Time, Java 8'deki yeni java.time. * Sınıflarına ilham verdi, ancak farklı bir mimariye sahip. Joda-Time'ı Java'nın eski sürümlerinde kullanabilirsiniz. Joda-Time, Java 8'de çalışmaya devam ediyor ve aktif olarak korunmaya devam ediyor (2014 itibariyle). Ancak, Joda-Time ekibi java.time'a geçişi tavsiye eder.

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

Daha ayrıntılı örnek kod (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 );

Konsola dökümü…

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

Çalıştırıldığında…

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

Saat dilimi çalışması yapan daha fazla örnek kod için benzer bir soruya verdiğim cevaba bakın .

Saat dilimi

JVM'nin geçerli varsayılan saat dilimine dolaylı olarak güvenmek yerine her zaman bir saat dilimi belirtmenizi öneririm (her an değişebilir!). Böyle bir güven, tarih-saat çalışmasında ortak bir karışıklık ve hata nedeni gibi görünmektedir.

Arama yaparken now()atanacak istenen / beklenen zaman dilimini geçirin. DateTimeZoneSınıfı kullanın .

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

Bu sınıf UTC saat dilimi için sabittir .

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

JVM'nin geçerli varsayılan saat dilimini gerçekten kullanmak istiyorsanız, kodunuzun kendi kendini belgelemesi için açık bir arama yapın.

DateTimeZone zoneDefault = DateTimeZone.getDefault();

ISO 8601

ISO 8601 formatları hakkında bilgi edinin . Hem java.time hem de Joda-Time, dizenin ayrıştırılması ve oluşturulması için bu standardın makul biçimlerini varsayılan olarak kullanır.


Aslında, java.util.Date , kaynak kodu katmanlarının altında gömülü bir zaman dilimine sahiptir. En pratik amaçlar için, bu zaman dilimi göz ardı edilir. Yani, steno olarak java.util.Date'in saat dilimi yok diyoruz. Ayrıca, gömülü saat dilimi, Date'in yönteminde kullanılan bölge değildirtoString ; bu yöntem JVM'nin geçerli varsayılan saat dilimini kullanır. Bu kafa karıştırıcı sınıftan kaçınmak ve Joda-Time ve java.time ile devam etmek için daha fazla neden.


2
DateTime.now().toDateTime(DateTimeZone.UTC)aradığım şey buydu! Teşekkürler!
Managarm

1
@Managarm Bunu kısaltabilirsiniz: DateTime nowUtc = DateTime.now ( DateTimeZone.UTC ) ;
Basil Bourque

2014-01-21T15:34:29.933-08:00new org.joda.time.DateTime()
Kullandığınız

1
@ GOXR3PLUS ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ).truncatedTo( ChronoUnit.MILLIS ).toOffsetDateTime().toString() Belirli bir saat dilimi için geçerli anı alıyoruz . Ardından, mikro / nanosları kapatın. Daha sonra, tam gelişmiş bir saat dilimi (yalnızca geçmişin, şimdinin ve gelecekteki değişikliklerin bir geçmişi belirli bir bölge). Son olarak, yönteminde OffsetDateTimevarsayılan olarak kullanılan standart ISO 8601 biçimindeki değeri temsil eden metin üretiyoruz toString.
Basil Bourque

Bu ayrıntılı açıklama için teşekkürler, ayrıca android destekler için +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 biçimini kullandıktan sonra neden dateFormatLocal ile ayrıştırıyorsunuz ... okuyarak mantıklı gelmiyor. Eminim işe yarıyor ama merak mı ediyorsun?
MindWire

2
setTimeZone yaptı (sanırım GMT ile aynı şeyi getTimeZone ("UTC") da kullanabilirsiniz?)
rogerdpack

6
ancak zaman, cihazın ayarlanan süresine bağlıdır. Kullanıcı cihazında yanlış bir süre ayarladıysa, yanlış UTC alırsınız. Eğer yanlışsam beni
düzelt

@BasavarajHampali ama günümüz dünyasında cihazların çoğu internete bağlı, bu da yanlış zamanı düzeltir
Akshat Agarwal

3
Eşgüdümlü Evrensel Zaman (UTC) ve Greenwich Ortalama Saati (GMT) arasında saat farkı yoktur
slott

86

Bu kesinlikle UTC zamanını döndürür: String ve Date nesneleri olarak!

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

Cevabım ben DATEFORMAT nasıl tanımlandığını gösterir unuttum: static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
Birisi bir yerde

21
Lütfen Java'da büyük harfle yöntem adlarını başlatmaktan kaçının. Yöntem adları için Java kodlama kurallarına bakın .
Florian Schrofner

2
Bu yanıta yönlendirildiğim için new Date(), cihaz saati yanlışsa Arama hiçbir zaman doğru UTC saatini döndürmez.
Sanoop

bu yöntem zaman alır cihaz takvimine bağlıdır?
Arnold Brown

Dikkat edilmesi gereken bir şey var. UTC'de bir Tarih veya Zaman Damgası alması gereken herhangi bir çözüm, anahtarın SimpleDateFormat'ı yeniden kullanmaması, UTC'yi bir dizeye almak için bir tane kullanması, ardından dizeyi bir Tarihe dönüştürürken başka bir UTC oluşturması gibi görünüyor veya Zaman Damgası Nesnesi. Aynı SimpleDateFormat'ı yeniden kullanmaya çalışırsanız, sonuçta oluşan Date / Timestamp Nesnesi UTC yerine yerel saat dilimine geri döner.
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

Aslında zaman değil, temsili değiştirilebilir.

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

Zaman, dünyanın herhangi bir noktasında aynıdır, ancak zaman algımız, yere bağlı olarak farklı olabilir.


Evet, güzel ve temiz bir çözüm. Sadece Takvim örneğini almak yerine yeni bir Date nesnesi oluşturmak etkisiz ise beni endişelendiriyor mu?
Beemo

JVM tarafından optimize edilecek ve HotSpot mümkün olan en etkili x86 kodunu çalıştıracak
Antonio

17

Takvim aGMTCalendar = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); Daha sonra aGMTCalendar nesnesi kullanılarak gerçekleştirilen tüm işlemler GMT saat dilimi ile yapılacak ve yaz saati uygulaması veya sabit ofsetler uygulanmayacaktır.

Yanlış!

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

ve

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

aynı zamanda dönecektir. İçin idem

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

17

Bu kod, geçerli saati UTC olarak yazdırır.

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

Sonuç

2013-10-26 14:37:48 UTC

14

Bu, Android'de UTC milisaniye elde etmek için çalışır.

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

7
sadece ofseti çıkarmanız mı gerekiyor?
tevch

c.add(Calendar.MILLISECOND, (-utcOffset))timezone ile Takvim almak için
Shanavas M

10

İşte Jon Skeet'in cevabı yanlış gibi görünüyor . Dedi ki:

java.util.Dateher zaman UTC'de bulunur. Sizi yerel saatte düşündüren nedir? Sorunun, yerel saat dilimini kullanan veya muhtemelen yerel saat dilimini kullanan bir Takvim örneği aracılığıyla görüntülediğinizden şüpheleniyorum Date.toString().

Ancak, kod:

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

hiç hayır Calendarve hayır kullanarak yerel saatleri (GMT (UTC saatleri) değil) verir SimpleDateFormat.

Bu yüzden bir şeyler yanlış görünüyor.

Yanıtları bir araya getiren kod:

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

yerel saatler yerine GMT saatlerini gösterir - bunun teorik olarak tarihi GMT'de depolayan ancak yerel saat dilimindeki saatleri geri veren getTime.getHours()bir Date()nesne oluşturacağı için eksik olduğuna dikkat edin .


6
Daha önce bu yanıtı görmemiştim, ancak kullanımdan kaldırılan Date.getHours()yöntemin belgelerini okuduysanız, bunu çok açık hale getiriyor: "Döndürülen değer, gün içindeki saati içeren veya bu saatle başlayan saati temsil eden bir sayıdır (0'dan 23'e kadar). bu Date nesnesi tarafından yerel saat diliminde yorumlandığı şekliyle anında gösterilen anında . " (Vurgu benim.) getHours()Yerel saat dilimi içindeki değeri yorumlayan yöntemdir - Datenesnenin kendisinin durumunun bir parçası değildir .
Jon Skeet

2
Jon Skeet'in doğru şekilde belirttiği gibi, bir java.util.Date nesnesinin saat dilimi yoktur . Ancak kafa karıştırıcı olarak, yöntemler toStringve getHoursçıkışlarına varsayılan saat dilimini uygulayın. Yani, saf programcılar bir Date'in saat dilimi var gibi göründüğü gibi kolayca kandırılırlar ama aslında yoktur.
Basil Bourque

7

UTC için ayarlanmış alanlara sahip bir Date nesnesi istiyorsanız, bunu Joda Time ile yapabilirsiniz :

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
Çok çalışıyorsun. Joda-Time bunu tek bir kod satırında yapabilir. Bu soruya kendi cevabımı gör . .toDateTimeYöntemi çağırın ve UTC saat dilimi için sabiti iletin.
Basil Bourque

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

6

Kullanabilirsiniz:

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

Daha sonra aGMTCalendar nesnesi kullanılarak yapılan tüm işlemler GMT saat dilimi ile yapılacak ve yaz saati uygulaması veya sabit ofsetler uygulanmayacaktır. Önceki posterin Date () nesnesinin her zaman bir GMT döndürdüğünü ve yerel zaman dilimine dönüştürülen tarih nesnesiyle bir şeyler yapana kadar olduğunu düşünüyorum.


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

Lütfen cevabınıza biraz açıklama ekleyin, diğer pek çok cevaptan farkı nedir?
akjoshi

bu yöntem zaman alır cihaz takvimine bağlıdır?
Arnold Brown

6

Bunu doğrudan kullanabilirsiniz

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

5

İle:

Calendar cal = Calendar.getInstance();

Ardından calgeçerli tarih ve saati alın.
Ayrıca şu saat dilimi için geçerli Tarih ve Saati de alabilirsiniz:

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

cal.get(Calendar.DATE);Başkalarının ayrıntılarını sorabilir veya başka bir Takvim sabiti kullanabilirsiniz.
Tarih ve Zaman Damgası Java'da kullanımdan kaldırıldı. Takvim sınıfı değil.


6
Date ve Timestamp'ın bazı yöntemleri ve yapıcıları kullanımdan kaldırılmıştır, ancak sınıfların kendileri değildir.
Powerlord

5

GMT Timestamp nesnesi almak için başka bir öneri:

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

Dize biçiminde GMT zamanı almanın başka bir yolu

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

İşte benim TOUTC uygulaması:

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

Muhtemelen onu geliştirmenin birkaç yolu var, ama benim için çalışıyor.


3

Sistem saatini belirli bir saat diliminde ve belirli bir biçimde oluşturmak için örnek kod.

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

}

Çıktı

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

Sadece bir yaratmak için, bu daha basit hale getirmek için Datede UTCsize kullanabilirsiniz Calendar:

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

Hangi Calendar"UTC" kullanmak için yeni bir örnek oluşturur TimeZone.

Bu Datetakvimden bir nesneye ihtiyacınız varsa kullanabilirsiniz getTime().


5
Bunun için getTime () çağrısı, saat dilimi bilgilerini kaybetmesine ve yerel saati döndürmesine neden olur.
RealCasually

3

Geçerli DateTime değerini UTC olarak dönüştürme:

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
Burada çok fazla iş yapıyorsunuz. (a) Tanımladığınız formatlayıcı bilmece varsayılan olarak zaten bir DateTime'da yerleşiktir; ISO 8601 dize desenini toStringalmak için DateTime'ı çağırmanız yeterlidir . (b) Zaman dilimleri arasında dönüştürmek için çok fazla kod. "ToDateTime" öğesini çağırmanız ve bir saat dilimi nesnesi iletmeniz yeterlidir. Bunun gibi: myDateTime.toDateTime( DateTimeZone.UTC ). Ve örneğini belirli bir zaman diliminde, bir dayalı bir saat dilimi nesnesi iletir özel isim , çağrı myDateTime.toDateTime( DateTimeZone.forID( "Asia/Tehran" ) ).
Basil Bourque

2

Bu benim için çalıştı, GMT'de zaman damgasını döndürür!

    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

Çevrimiçi NTP Sunucusundan doğru UTC Saatini almak için bu Sınıfı kullanı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);             
}

}

Ve şununla kullan:

        long now = 0;

        NTP_UTC_Time client = new NTP_UTC_Time();

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

DateTimeString işlevini kullanmak için UTC Time "now" 'a ihtiyacınız varsa:

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

ve aşağıdakilerle birlikte kullanın:

String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);

Tek satırda <br/> <pre> <code> Takvim utcTime = Calendar.getInstance (). Add (Calendar.MILLISECOND, -time.getTimeZone (). GetOffset (time.getTimeInMillis ())); </pre> < / code>
Harun

1
Evet, ancak bu kullanıcı tarafından manuel olarak yanlış bir DateTime olarak değiştirilebilen yerel Aygıt Saati'ni çağırır
Ingo

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

1

Basitleştirmek gerekirse. Bir takvim nesnesi saat dilimi hakkında bilgi depolar, ancak cal.getTime () işlemini gerçekleştirdiğinizde saat dilimi bilgileri kaybolur. Bu yüzden Timezone dönüşümleri için DateFormat sınıflarını kullanmanızı tavsiye edeceğim ...


1

bu benim uygulama:

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

Tarihi ayrıştırmaktan kaçınmak ve sadece GMT'de bir zaman damgası istiyorsanız, şunları kullanabilirsiniz:

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

0

Joda saatini kullanıyorsanız ve yerel ofsetiniz olmadan geçerli saati milisaniye olarak istiyorsanız, bunu kullanabilirsiniz:

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

Çıktı:

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

Tarih biçimini gerektiği gibi değiştirebilirsiniz.


1
Lütfen gençlere uzun süredir eskimiş ve kötü şöhretli olanları kullanmayı öğretmeyin SimpleDateFormat. Bugün java.time, modern Java tarih ve saat API'sında çok daha iyi var . Ayrıca, şu anda Dan, Antonio ve diğerlerinin cevaplarında olmayan ne sağlıyorsunuz?
Ole VV

2
(a) Bu Yanıt, onlarca mevcut Yanıt'a nasıl değer katar? (b) Burada kullanılan zahmetli dersler yıllar önce modern java.time dersleri ile tamamlanmıştı. 2018'de kullanımlarını önermek kötü tavsiye.
Basil Bourque

0

Java.time paketini kullanın ve aşağıdaki kodu ekleyin:

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

veya

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

uygulama ihtiyacınıza göre.


(A) ZoneOffsetBir saat dilimi ( ZoneId) yerine ofset ( ) kullanılıyorsa OffsetDateTime, daha uygun olur ZonedDateTime. (B) LocalDateTimeherhangi bir zaman dilimi veya UTC'den sapma kavramına sahip olmadığından geçerli anı yakalamak için kullanılmamalıdır. (C) Önceden var olan diğer Cevaplar bu materyali kapladı ve daha iyi bir iş çıkardı. Bu cevabın nasıl değer kattığını anlamıyorum.
Basil Bourque
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.