Java'da değerlerle Tarih Nesnesi nasıl oluşturulur?


91

2014-02-11 tarihi için bir tarih nesnesine ihtiyacım var. Bunu doğrudan böyle yapamam

Date myDate = new Date(2014, 02, 11);

Bu yüzden aşağıdaki gibi yapıyorum,

Calendar myCalendar = new GregorianCalendar(2014, 2, 11);
Date myDate = myCalendar.getTime();

Java'da tarih nesnesi oluşturmanın kolay bir yolu var mı?


7
Yaklaşımınızda kolay olmayan nedir?
giorashc

3
"Kolay bir yolu var mı?" Bunun olabileceği kadar kolay olmadığını düşündüren nedir? Saatler ve tarihler düşündüğünüzden çok daha karmaşık. Birden çok takvim ve birden çok saat dilimi vardır.
Raedwald

5
Bir satır gibi Date myDate = new GregorianCalendar(2014, 2, 11).getTime();?
Elliott Frisch

2
Bu Soru'da görüldüğü gibi bir tamsayı değişmezinde baştaki sıfır kullanmaya dikkat edin 02. Java'da bu, ondalık (taban-10) sayı yerine sekizlik (taban-8) sayı anlamına gelir .
Fesleğen Bourque

2
Bilginize gibi korkunç zahmetli eski tarih-saat sınıfları java.util.Date, java.util.Calendarve java.text.SimpleDateFormatşimdi mirası supplanted, java.time sonra Java 8 ve yerleşik sınıflara. Oracle'ın Eğitimi bölümüne bakın .
Basil Bourque

Yanıtlar:


108

Anladım: ay olarak 2'yi geçmek size beklenmedik bir sonuç verebilir: Takvim API'sinde ay sıfır tabanlıdır. 2 aslında Mart anlamına gelir.

Takvim'i kullanmanın zaten yeterince kolay olduğunu düşündüğümden, aradığınız "kolay" bir yol nedir bilmiyorum.

Ay için doğru sabitleri kullanmayı unutmayın:

 Date date = new GregorianCalendar(2014, Calendar.FEBRUARY, 11).getTime();

Başka bir yol da genellikle şu şekilde kullandığım DateFormat'ı kullanmaktır:

 public static Date parseDate(String date) {
     try {
         return new SimpleDateFormat("yyyy-MM-dd").parse(date);
     } catch (ParseException e) {
         return null;
     }
  }

böylece basitçe yazabilirim

Date myDate = parseDate("2014-02-14");

Yine de tercih ettiğim başka bir alternatif: Artık Java Date / Calendar kullanmayın. JODA Zamanına veya Java Zamanına geçiş yapın (JSR310 olarak da bilinir, JDK 8+ sürümlerinde mevcuttur). LocalDateTarafından kolayca oluşturulabilen bir tarihi temsil etmek için kullanabilirsiniz .

LocalDate myDate =LocalDate.parse("2014-02-14");
// or
LocalDate myDate2 = new LocalDate(2014, 2, 14);
// or, in JDK 8+ Time
LocalDate myDate3 = LocalDate.of(2014, 2, 14);

1
.toTime()yok. O olmalıdır .getTime()(bkz Java Dokümanlar )
0xJoKe

Üzgünüm bir yazım hatası. OP'nin aramak için doğru yöntemi zaten bildiğini düşünüyorum: P
Adrian Shum

Haklı olduğundan oldukça eminim. Ancak (benim gibi), ihtiyaç duyulduğunda her zaman bakması gerekenler için sinir bozucu.
Düzeltdiğiniz

1
return new SimpleDateFormat("yyyy-mm-dd").parse(date) olmalıdırreturn new SimpleDateFormat("yyyy-MM-dd").parse(date)
aks

İyi yakalama. Neden böyle bir hata yaptım bilmiyorum. Düzeltme
Adrian Shum

34

tl; dr

LocalDate.of( 2014 , 2 , 11 )

Korkunç eski java.util.Datesınıfı kullanmakta ısrar ediyorsanız , modern java.time sınıflarından dönüştürün .

java.util.Date                        // Terrible old legacy class, avoid using. Represents a moment in UTC. 
.from(                                // New conversion method added to old classes for converting between legacy classes and modern classes.
    LocalDate                         // Represents a date-only value, without time-of-day and without time zone.
    .of( 2014 , 2 , 11 )              // Specify year-month-day. Notice sane counting, unlike legacy classes: 2014 means year 2014, 1-12 for Jan-Dec.
    .atStartOfDay(                    // Let java.time determine first moment of the day. May *not* start at 00:00:00 because of anomalies such as Daylight Saving Time (DST).
        ZoneId.of( "Africa/Tunis" )   // Specify time zone as `Continent/Region`, never the 3-4 letter pseudo-zones like `PST`, `EST`, or `IST`. 
    )                                 // Returns a `ZonedDateTime`.
    .toInstant()                      // Adjust from zone to UTC. Returns a `Instant` object, always in UTC by definition.
)                                     // Returns a legacy `java.util.Date` object. Beware of possible data-loss as any microseconds or nanoseconds in the `Instant` are truncated to milliseconds in this `Date` object.   

Detaylar

"Kolay" istiyorsanız , Java ile birlikte gelen sorunlu java.util.Date & .Calendar sınıfları yerine Java 8'deki yeni java.time paketini kullanıyor olmalısınız .

java.time

Java 8 ve sonraki sürümlerde yerleşik olan java.time çerçevesi, zahmetli eski java.util.Date/.Calendar sınıflarının yerini alır.

Yalnızca tarih

görüntü açıklamasını buraya girin

Bir LocalDatesınıf her zaman günün-veya saat dilimi bulunmayan bir tarih salt değeri temsil java.time tarafından sunulmaktadır. Örneğin, Paris'te yeni bir gün Montréal'den daha erken doğduğu için, bir tarihi belirlemek için bir saat dilimine ihtiyacınız vardır. ZoneIdSınıf zaman dilimleri içindir.

ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
LocalDate today = LocalDate.now( zoneId );

Konsola aktar:

System.out.println ( "today: " + today + " in zone: " + zoneId );

bugün: 2015-11-26 bölgesinde: Asya / Singapur

Veya yılı, ayı, günü belirtmek için bir fabrika yöntemi kullanın.

LocalDate localDate = LocalDate.of( 2014 , Month.FEBRUARY , 11 );

localDate: 2014-02-11

Veya bir DayOfWeeknumaralandırma nesnesi yerine 1-12 numaralı bir ay geçirin.

LocalDate localDate = LocalDate.of( 2014 , 2 , 11 );

Saat dilimi

görüntü açıklamasını buraya girin

LocalDateSiz onu bir saat dilimine ayarlayana kadar A'nın gerçek bir anlamı yoktur. Java.time'da, bir ZonedDateTimenesne oluşturmak için bir saat dilimi uygularız . Bu aynı zamanda günün saati anlamına da geliyor, ama ne zaman? Genellikle günün ilk anıyla gitmek mantıklıdır. Bunun zaman anlamına geldiğini düşünebilirsiniz 00:00:00.000, ancak Yaz Saati Uygulaması (DST) ve belki diğer anormallikler nedeniyle her zaman doğru değildir. O zamanı varsaymak yerine, java.time'ı arayarak günün ilk anını belirlemesini istiyoruz atStartOfDay.

Bir belirtme uygun bir zaman dilimi adı biçiminde continent/regiongibi America/Montreal, Africa/Casablancaya da Pacific/Auckland. Hiçbir zaman gibi 3-4 harfli bir kısaltma kullanın ESTveya ISToldukları gibi değil , gerçek zaman dilimleri, değil standardize ve hatta benzersiz değil (!).

ZoneId zoneId = ZoneId.of( "Asia/Singapore" );
ZonedDateTime zdt = localDate.atStartOfDay( zoneId );

zdt: 2014-02-11T00: 00 + 08: 00 [Asya / Singapur]

UTC

görüntü açıklamasını buraya girin

Arka uç çalışması için (iş mantığı, veritabanı, veri depolama ve değişim) genellikle UTC saat dilimini kullanırız. Java.time'da Instantsınıf, UTC'de zaman çizelgesindeki bir anı temsil eder. Bir Anlık nesne, bir ZonedDateTime'dan çağrılarak çıkarılabilir toInstant.

Instant instant = zdt.toInstant();

anlık: 2014-02-10T16: 00: 00Z

Dönüştürmek

java.util.DateSınıfı tamamen kullanmaktan kaçınmalısınız . Ancak java.time için henüz güncellenmemiş eski kodla birlikte çalışmanız gerekiyorsa , ileri-geri dönüştürebilirsiniz. Eski sınıflara eklenen yeni dönüştürme yöntemlerine bakın.

java.util.Date d = java.util.from( instant ) ;

…ve…

Instant instant = d.toInstant() ;

Hem modern hem de eski Java'daki tüm tarih-saat türlerinin 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 edinmek için Oracle Eğitimi'ne bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310'dur .

Şu anda bakım modunda olan Joda-Time projesi, java.time sınıflarına geçişi tavsiye ediyor .

Java.time nesnelerini doğrudan veritabanınız ile takas edebilirsiniz . JDBC 4.2 veya üstü ile uyumlu bir JDBC sürücüsü kullanın . Dizelere gerek yok, derslere gerek yok . Hibernate 5 ve JPA 2.2 java.time'ı destekler .java.sql.*

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


GÜNCELLEME: Joda-Time kitaplığı artık bakım modundadır ve java.time sınıflarına geçişi tavsiye eder . Tarih için bu bölümü yerinde bırakıyorum.

Joda-Zaman

Birincisi, Joda-Time mantıklı bir numaralandırma kullanıyor, bu yüzden Şubat 2değil 1. Başka bir şey, bir Joda-Time DateTime, saat dilimine sahip gibi görünen ancak olmayan java.util.Date'den farklı olarak atanmış saat dilimini gerçekten bilir.

Ve saat dilimini unutma. Aksi takdirde, JVM'nin varsayılanını alacaksınız.

DateTimeZone timeZone = DateTimeZone.forID( "Asia/Singapore" );
DateTime dateTimeSingapore = new DateTime( 2014, 2, 11, 0, 0, timeZone );
DateTime dateTimeUtc = dateTimeSingapore.withZone( DateTimeZone.UTC );

java.util.Locale locale = new java.util.Locale( "ms", "SG" ); // Language: Bahasa Melayu (?). Country: Singapore.
String output = DateTimeFormat.forStyle( "FF" ).withLocale( locale ).print( dateTimeSingapore );

Konsola aktar…

System.out.println( "dateTimeSingapore: " + dateTimeSingapore );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "output: " + output );

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

dateTimeSingapore: 2014-02-11T00:00:00.000+08:00
dateTimeUtc: 2014-02-10T16:00:00.000Z
output: Selasa, 2014 Februari 11 00:00:00 SGT

Dönüştürmek

Diğer sınıflarla kullanmak için java.util.Date biçimine dönüştürmeniz gerekirse…

java.util.Date date = dateTimeSingapore.toDate();

4
Sadece bir yorum. Gibi alanlarda sıfırların önüne sıfırlama uygulaması new DateTime( 2014, 02, 11, 0, 0, timeZone );muhtemelen tercih edilmez. Bu durumda çalışır, ancak rağmen, Ağustos ve Eylül geçiyoruz için derlemek olmaz 08ve 090 anlamına sekizlik sunumu ile bir int literal önek olarak. Hatta daha önce yıllarca size beklenmeyen değerler verecektir 1000örn new DateTime( 0100, 02, 01, 0, 0, timeZone );kimse 100AD olmasını bekliyoruz olabileceğini ama aslında 64AD olduğunu
Adrian Shum

@AdrianShum Yikes! Tam sayıdaki sıfır gibi masum küçük bir yazım hatasının bu kadar kötü bir yan etkisi olabileceğini hiç bilmiyordum. Teşekkürler.
Fesleğen Bourque

2
Sevgili Aşağı Seçmen, oyunuzla birlikte bir eleştiri bırakın.
Basil Bourque

"Korkunç eski java.util.Date sınıfını kullanmakta ısrar ediyorsanız". Pek çok sağlayıcı Java üzerinde JDK7'nin ötesinde çalışan tomcat sunucuları sunmuyor, bu yüzden, daha yeni şeyleri kullanmaya
bayılırken

@KimvdLinde Cevabımı daha dikkatli okuyun. Mermilere bakın. "Java SE 6 ve Java SE 7" kelimelerini bulun.
Basil Bourque

14

Bence en iyi yol bir SimpleDateFormatnesne kullanmaktır .

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateString = "2014-02-11";
Date dateObject = sdf.parse(dateString); // Handle the ParseException here

Y .. Ve YYYY'yi asla kullanmadığınızdan emin olun - yyyy kullanın - özellikle bunu ayrıştırma yerine biçimle tersine yapıyorsanız. Garip sonuçlar alıyorsun !!! Buraya bakın: code.sololearn.com/c0EYUAOc92uQ/#java
JGFMK

9

Java8'den:

import java.time.Instant;
import java.util.Date;

Date date = Date.from(Instant.parse("2000-01-01T00:00:00.000Z"))

2

Bunu dene

 Calendar cal = Calendar.getInstance();
    Date todayDate = new Date();
    cal.setTime(todayDate);

    // Set time fields to zero
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    todayDate = cal.getTime();

1
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss", Locale.ENGLISH);
//format as u want

try {
    String dateStart = "June 14 2018 16:02:37";
    cal.setTime(sdf.parse(dateStart));
    //all done
} catch (ParseException e) {
    e.printStackTrace();
}

Korkunç Calendarve SimpleDateFormatsınıfların yerini yıllar önce java.time sınıfları aldı. 2018'de kullanımlarını önermek kötü bir tavsiye.
Basil Bourque

Bu Cevap, bu Sorunun ayrıntılarına değinmemektedir.
Basil Bourque

1
"API seviyeleri" derken Android'i kastettiğinizi varsayıyorum. Ancak bu, Android'e özgü bir Soru değildir. Ayrıca, java.time işlevlerinin çoğu , ThreeTen-Backport projesinde Java 6 & 7'ye geri taşınır . ThreeTenABP projesinde Android'e daha fazla uyarlandı . Yani, bu berbat eski tarih-saat sınıflarını kullanmanıza gerek yok. Java.time sınıfları kökten iyidir.
Basil Bourque

Bu yorum için teşekkürler.Bu kütüphane tarih farkı ve saat farklılıkları gibi işlevler sağlıyor mu?
Syed Danimarkalı Haider

1
Evet. Bu konudaki mevcut birçok Soru ve Cevap için Yığın Taşması'nı arayın. Ve ThreeTen-Extra projesini de görün (eski Android'e geri taşınmamış ).
Basil Bourque

0

En basit yollar:

Date date = Date.valueOf("2000-1-1");
LocalDate localdate = LocalDate.of(2000,1,1);
LocalDateTime localDateTime = LocalDateTime.of(2000,1,1,0,0);

Kullandığınız java.sql.Datesınıf kötü tasarlanmış ve modası geçmiş olduğu için ilkinden kaçınmalısınız . LocalDateİkinci satırdaki gibi kullanmanızı tavsiye ederim . Alışkanlığım, LocalDate.of(2000, Month.JANUARY, 1)okumayı biraz daha net buluyorum.
Ole VV

ve yanıt LocalDate bildirimini içerdiğinden, yalnızca Date nesnesi sorulmadığından (kullanımdan kaldırılmadı ve bazen kullanıldı) ...
Adam Silenko

-1
import java.io.*;
import java.util.*;
import java.util.HashMap;

public class Solution 
{

    public static void main(String[] args)
    {
        HashMap<Integer,String> hm = new HashMap<Integer,String>();
        hm.put(1,"SUNDAY");
        hm.put(2,"MONDAY");
        hm.put(3,"TUESDAY");
        hm.put(4,"WEDNESDAY");
        hm.put(5,"THURSDAY");
        hm.put(6,"FRIDAY");
        hm.put(7,"SATURDAY");
        Scanner in = new Scanner(System.in);
        String month = in.next();
        String day = in.next();
        String year = in.next();

        String format = year + "/" + month + "/" + day;
        Date date = null;
        try
        {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
            date = formatter.parse(format);
        }
        catch(Exception e){
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        System.out.println(hm.get(dayOfWeek));
    }
}

SimpleDateFormat formatlayıcı, Tarihi bize göre biçimlendirmek için kullanılabilir. ve ardından Tarih Nesnesinin içinde ayrıştırma. Yukarıdaki program, herhangi bir tarih vererek haftanın günlerinin nasıl alınacağını göstermektedir.
Ankush

-5

Sanırım tarihin php'den geliyor ve html (dom) veya? Tüm tarihleri ​​ve zaman damgalarını hazırlamak için bir php işlevim var. Bu, gerekli olan bir dizilişi döndürür.

$timeForJS = timeop($datetimeFromDatabase['payedon'], 'js', 'local'); // save 10/12/2016 09:20 on var

bu format js üzerinde yeni Tarih oluşturmak için kullanılabilir ...

<html>
   <span id="test" data-date="<?php echo $timeForJS; ?>"></span>
   <script>var myDate = new Date( $('#test').attr('data-date') );</script>
</html>

Söyleyeceğim şey, hayatınızı kolaylaştıran kendi işlevinizi sarmalayın. Fonksiyonlarımı örnek olarak kullanabilirsin ama cm'lerime dahil 1'e 1 kopyalayıp yapıştıramazsın :)

    function timeop($utcTime, $for, $tz_output = 'system')
{
    // echo "<br>Current time ( UTC ): ".$wwm->timeop('now', 'db', 'system');
    // echo "<br>Current time (USER): ".$wwm->timeop('now', 'db', 'local');
    // echo "<br>Current time (USER): ".$wwm->timeop('now', 'D d M Y H:i:s', 'local');
    // echo "<br>Current time with user lang (USER): ".$wwm->timeop('now', 'datetimes', 'local');

    // echo '<br><br>Calculator test is users timezone difference != 0! Tested with "2014-06-27 07:46:09"<br>';
    // echo "<br>Old time (USER -> UTC): ".$wwm->timeop('2014-06-27 07:46:09', 'db', 'system');
    // echo "<br>Old time (UTC -> USER): ".$wwm->timeop('2014-06-27 07:46:09', 'db', 'local');

    /** -- */
    // echo '<br><br>a Time from db if same with user time?<br>';
    // echo "<br>db-time (2019-06-27 07:46:09) time left = ".$wwm->timeleft('2019-06-27 07:46:09', 'max');
    // echo "<br>db-time (2014-06-27 07:46:09) time left = ".$wwm->timeleft('2014-06-27 07:46:09', 'max', 'txt');

    /** -- */
    // echo '<br><br>Calculator test with other formats<br>';
    // echo "<br>2014/06/27 07:46:09: ".$wwm->ntimeop('2014/06/27 07:46:09', 'db', 'system');

    switch($tz_output){
        case 'system':
            $tz = 'UTC';
            break;

        case 'local':
            $tz = $_SESSION['wwm']['sett']['tz'];
            break;

        default:
            $tz = $tz_output;
            break;
    }

    $date = new DateTime($utcTime,  new DateTimeZone($tz));

    if( $tz != 'UTC' ) // Only time converted into different time zone
    {
        // now check at first the difference in seconds
        $offset = $this->tz_offset($tz);
        if( $offset != 0 ){
            $calc = ( $offset >= 0  ) ? 'add' : 'sub';
            // $calc = ( ($_SESSION['wwm']['sett']['tzdiff'] >= 0 AND $tz_output == 'user') OR ($_SESSION['wwm']['sett']['tzdiff'] <= 0 AND $tz_output == 'local') ) ? 'sub' : 'add';
            $offset = ['math' => $calc, 'diff' => abs($offset)];
            $date->$offset['math']( new DateInterval('PT'.$offset['diff'].'S') ); // php >= 5.3 use add() or sub()
        }
    }

    // create a individual output
    switch( $for ){
        case 'js':
            $format = 'm/d/Y H:i'; // Timepicker use only this format m/d/Y H:i without seconds // Sett automatical seconds default to 00
            break;
        case 'js:s':
            $format = 'm/d/Y H:i:s'; // Timepicker use only this format m/d/Y H:i:s with Seconds
            break;
        case 'db':
            $format = 'Y-m-d H:i:s'; // Database use only this format Y-m-d H:i:s
            break;
        case 'date':
        case 'datetime':
        case 'datetimes':
            $format = wwmSystem::$languages[$_SESSION['wwm']['sett']['isolang']][$for.'_format']; // language spezific output
            break;
        default:
            $format = $for;
            break;
    }

    $output = $date->format( $format );

    /** Replacement
     * 
     * D = day short name
     * l = day long name
     * F = month long name
     * M = month short name
     */
    $output = str_replace([
        $date->format('D'),
        $date->format('l'),
        $date->format('F'),
        $date->format('M')
    ],[
        $this->trans('date', $date->format('D')),
        $this->trans('date', $date->format('l')),
        $this->trans('date', $date->format('F')),
        $this->trans('date', $date->format('M'))
    ], $output);

    return $output; // $output->getTimestamp();
}

2
Neden> 2 yaşındaki bir Java sorusunu PHP'de yanıtıyla yanıtlıyorsunuz?
Alan Hay
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.