Java takvimini kullanarak X gününü bir tarihten nasıl çıkarabilirim?


180

Herkes bir tarihten X gün çıkarmak için Java takvim kullanarak basit bir yol biliyor musunuz?

Java'daki bir tarihten X gününü doğrudan çıkarmama izin veren herhangi bir işlev bulamadım. Birisi beni doğru yöne yönlendirebilir mi?


Bilginize, zahmetli eski tarih-saat sınıfları gibi java.util.Calendarşimdi eski supplanted, java.time sınıfları. Oracle'ın Öğreticisine bakın .
Basil Bourque

Yanıtlar:


309

Alındığı burada docs :

Takvimin kurallarına bağlı olarak, belirtilen takvim alanına belirtilen süreyi toplar veya çıkarır. Örneğin, takvimin geçerli saatinden 5 gün çıkarmak için şunları arayarak gerçekleştirebilirsiniz:

Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).

1
Her zaman beklediğiniz gibi dönmediği için bunu yaparken dikkatli olun.
carson

1
Bu cevapların çok sayıda oyu var, ancak kullanımı güvenli mi? ya da bu daha iyi: stackoverflow.com/a/10796111/948268
Kuldeep Jain

44
İstediğiniz Calendar.DAY_OF_MONTHgibi aylar arasında ruloyu işlemeyeceği için bu durumda kullanmazsınız . Calendar.DAY_OF_YEARBunun yerine kullanın
algoritmalar

4
Görünüşe göre, bu eklediğinizde DAY_OF_MONTH veya DAY_OF_YEAR stackoverflow.com/q/14065198/32453
rogerdpack

@carson Bu yaklaşımla ilgili sorunlardan bazıları nelerdir?
tatmanblue

38

addYöntemi kullanabilir ve negatif bir sayı iletebilirsiniz. Ancak, Calendaraşağıdaki gibi sınıfı kullanmayan daha basit bir yöntem de yazabilirsiniz

public static void addDays(Date d, int days)
{
    d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}

Bu, tarihin zaman damgası değerini alır (çağdan bu yana geçen milisaniye) ve uygun milisaniye sayısını ekler. Çıkarma işlemi yapmak için days parametresi için negatif bir tam sayı iletebilirsiniz. Bu, "uygun" takvim çözümünden daha basit olacaktır:

public static void addDays(Date d, int days)
{
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    c.add(Calendar.DATE, days);
    d.setTime( c.getTime().getTime() );
}

Bu çözümlerin her ikisinin de Datetamamen yeni bir döndürme yerine parametre olarak geçirilen nesneyi değiştirdiğini unutmayın Date. Her iki işlev de istenirse bunu yapmak için kolayca değiştirilebilir.


3
.SetTime ve .add öğelerinin Takvim'in statik yöntemleri olduğuna inanmayın. C değişkenini kullanıyor olmalısınız.
Edward

@Edward: haklısın, hatayı işaret ettiğin için teşekkürler, kodu şimdi düzgün çalışması için düzelttim.
Eli Courtwright

3
İlk yöne dikkat edin, örneğin leapyear günlerle uğraşırken başarısız olabilir: stackoverflow.com/a/1006388/32453
rogerdpack

Bilginize, zahmetli eski tarih-saat sınıfları gibi java.util.Calendarşimdi eski supplanted, java.time sınıfları. Oracle'ın Öğreticisine bakın .
Basil Bourque

36

Anson'un cevabı basit vaka için iyi çalışacaktır, ancak daha karmaşık tarih hesaplamaları yapacaksanız Joda Time'a göz atmanızı tavsiye ederim . Hayatınızı çok daha kolaylaştıracak.

Joda zamanında yapabileceğiniz FYI

DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);

1
@ShahzadImam, DateTimeFormat'a göz atın . DateTime örneklerini rasgele biçimler kullanarak dizelere dönüştürmenize izin verir. Java.text.DateFormat sınıfına çok benzer.
Mike Deck

1
Java 8'den itibaren java.time'ı
toidiu

FYI, Joda-Time projesi şu anda bakım modunda ve ekip java.time sınıflarına geçişi tavsiye ediyor . Oracle'ın Öğreticisine bakın .
Basil Bourque

19

tl; Dr.

LocalDate.now().minusDays( 10 )

Zaman dilimini belirtmek daha iyidir.

LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )

ayrıntılar

java.util.Date/ Gibi Java'nın ilk sürümleriyle birlikte gelen eski tarih-saat sınıflarının .Calendarzahmetli, kafa karıştırıcı ve kusurlu olduğu kanıtlanmıştır. Onlardan kaçının.

java.time

Java 8 ve üstü bu eski sınıfları yeni java.time çerçevesiyle tamamlar. Bkz. Öğretici . Joda-Time'dan esinlenilen ve ThreeTen-Extra projesi ile genişletilen JSR 310 tarafından tanımlanmıştır . ThreeTen-Backport projesi, sınıfları Java 6 ve 7'ye geri bağlar; ThreeTenABP projesi Android için.

Soru belirsizdir, sadece tarih mi yoksa tarih zamanı mı istediği açık değildir.

LocalDate

Yalnızca tarih için, günün saati olmadan, LocalDatesınıfı kullanın . "Bugün" gibi bir tarihin belirlenmesinde çok önemli bir saat dilimi olduğunu unutmayın.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );

ZonedDateTime

Bir tarih-zaman demek, o zaman kullanmak Instantiçinde çizelgesi üzerinde bir an olsun sınıfını UTC . Oradan, bir ZonedDateTimenesneyi almak için bir saat dilimine ayarlayın .

Instant now = Instant.now();  // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );

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.

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

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 .

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?

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 .


Bu, diğer seçeneklere göre çok daha iyi bir gelişmedir (aynı zamanda çok daha yenidir ve yeni yöntemleri kullanır). Bu sorunu şimdi ziyaret ediyorsanız, Bu yol.
Shourya Bansal


5

Bunun yerine kendi yazma addDaysEli önerdiği gibi, ben kullanmayı tercih ediyorum DateUtilsdan Apache . Özellikle projenizde birden fazla yer kullanmanız gerektiğinde kullanışlıdır.

API diyor ki:

addDays(Date date, int amount)

Bir tarihe yeni bir nesne döndüren birkaç gün ekler.

Yeni bir Datenesne döndürdüğünü ve bir öncekinin kendisinde değişiklik yapmadığını unutmayın.


2

Aşağıdaki ile kolayca yapılabilir

Calendar calendar = Calendar.getInstance();
        // from current time
        long curTimeInMills = new Date().getTime();
        long timeInMills = curTimeInMills - 5 * (24*60*60*1000);    // `enter code here`subtract like 5 days
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

        // from specific time like (08 05 2015)
        calendar.set(Calendar.DAY_OF_MONTH, 8);
        calendar.set(Calendar.MONTH, (5-1));
        calendar.set(Calendar.YEAR, 2015);
        timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
        calendar.setTimeInMillis(timeInMills);
        System.out.println(calendar.getTime());

Bu cevap, artık eski olan, java.time sınıfları tarafından desteklenen korkunç eski tarih-saat sınıfları kullanılarak tavsiye edilmez. Ayrıca, bu kod, 24 saatlik günleri varsayarak, zaman diliminin önemli sorununu göz ardı eder. Başka bir sorun, yalnızca tarih sorununu çözmek için bir tarih-saat sınıfı kullanmaktır. Kullanımı LocalDateçok daha basit ve daha uygundur.
Basil Bourque

1

Birisi Joda Time'ı tavsiye etti - bu CalendarDate sınıfını kullanıyorum http://calendardate.sourceforge.net

Joda Time için biraz rakip bir proje, ama sadece 2 sınıfta çok daha temel. Projemden daha büyük bir paket kullanmak istemediğim için çok kullanışlı ve ihtiyacım olan şey için harika çalıştı. Java muadillerinden farklı olarak, en küçük birimi gündür, bu yüzden gerçekten bir tarihtir (milisaniyeye veya başka bir şeye sahip olmamak). Tarihi oluşturduktan sonra, çıkartmak için yaptığınız tek şey 5 gün geri dönmek için myDay.addDays (-5) gibi bir şeydir. Haftanın gününü ve bunun gibi şeyleri bulmak için kullanabilirsiniz. Başka bir örnek:

CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);

Ve:

//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
    dayLabel = cdf.format(currDay);
    if (currDay.equals(today))
        dayLabel = "Today";//print "Today" instead of the weekday name
    System.out.println(dayLabel);
    currDay = currDay.addDays(1);//go to next day
}

1

Java.time.Instant sınıfı kullanılarak herhangi bir zaman biriminin (ay, gün, saat, dakika, saniye, ...) çıkarılması veya eklenmesinin temiz ve güzel bir yolunun elde edilebileceğine inanıyorum .

Geçerli saatten 5 gün çıkarmak ve sonucu Tarih olarak almak için örnek:

new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());

1 saat çıkarmak ve 15 dakika eklemek için başka bir örnek:

Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));

Daha fazla doğruluğa ihtiyacınız varsa, Instance nanosaniyeye kadar ölçüm yapar. Nanosaniye kısmını manipüle eden yöntemler:

minusNano()
plusNano()
getNano()

Ayrıca, Tarihin Anında Arama kadar doğru olmadığını unutmayın.


1
Veya tada bağlı olarak, biraz daha kısa:Date.from(Instant.now().minus(5, ChronoUnit.DAYS))
Ole VV

1
Güzel! Haklısın. Aslında bunu kullanmak için yanıtı güncelledim ve bu durumda da çok güçlü olan java.time.Duration sınıfının bir kullanımını gösterdim.
Yordan Boev

0

Eli Courtwright ikinci çözümü yanlış, şöyle olmalı:

Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());

2
Eli'nin çözümündeki işlevin adı addDays; onun çözümü doğrudur. Tarihten gün çıkarmak istiyorsanız, için negatif bir değer iletirsiniz days.
Thomas Upton

Bu, programlayıcının işlevi oluştururken belirtmesi gereken bir şey, değil mi? : P
user178973
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.