Joda-Time'da iki tarih arasındaki gün sayısı


336

İki Joda-Time DateTime örneği arasındaki Günler arasındaki farkı nasıl bulabilirim ? 'Günlerdeki fark' ile, başlangıç ​​Pazartesi ve bitiş Salı ise, başlangıç ​​ve bitiş tarihlerinin saat / dakika / saniyesine bakılmaksızın 1 dönüş değeri bekliyorum.

Days.daysBetween(start, end).getDays() başlangıç ​​akşam ise ve sabah bitiyorsa bana 0 verir.

Ben de daha az önemsiz alanları 'görmezden' genel bir yol olacağını umuyordum diğer tarih alanları ile aynı sorunu yaşıyorum.

Diğer bir deyişle, Şubat ile 4 Mart arasındaki aylar da, saat 14:45 ile 15:12 arasındaki saatler de 1 olacaktır. Bununla birlikte, 14:01 ve 14:55 arasındaki saat farkı 0 olacaktır.

Yanıtlar:


393

Can sıkıcı bir şekilde, withTimeAtStartOfDay yanıtı yanlış, ancak yalnızca ara sıra. İstediğiniz:

Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()

Görünüşe göre "gece yarısı / günün başlangıcı" bazen 1 am (bazı yerlerde gün ışığından yararlanma bu şekilde olur) anlamına gelir;

// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
                               end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
                               end.toLocalDate()).getDays());
// prints 1

LocalDateTüm mesele bir yana doğru gidiyor .


Days.daysBetweenYanlış olduğunu düşündüğünüz belirli verilerle örnek bir durum sunabilir misiniz ?
Basil Bourque

Kullanmayı söylediğin zaman Instant, sadece bahsetmiyorsun değil start.toInstant()mi?
Patrick M

@PatrickM Evet, öyleydim. Yansıtma üzerine, bunun hangi kısıtlamaları getireceği tam olarak açık değil, bu yüzden bu son cümleyi kaldıracağım. Teşekkürler!
Alice Purcell

Doc arasında, BÜTÜN gün sayısını döndürdüğünü söylüyor . Benim durumumda 2 gün 1 saat bana 3 gün dönmelidir. Örneğinizde 2 gün döndürür. bunu arşivlemenin bir yolu var mı?
Sujit Joshi

@SujitJoshi Korkarım Sorunuzu anlamıyorum. Tam bir Stack Overflow sorusu göndermeyi ve benim için buraya bir bağlantı yapıştırmayı öneriyorum :)
Alice Purcell

186

Days Sınıf

DaysSınıfı withTimeAtStartOfDayyöntemle kullanmak işe yarayacaktır:

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

1
Teşekkürler! Joda ile android.text.format.DateUtils.getRelativeTimeSpanString () davranışını elde etmeye çalışıyordum ve bu gerçekten yararlı oldu.
gosho_ot_pochivka

1
Efendim, bu yazıya referansla toDateMidnight()DateTime türündeki yöntem kullanımdan kaldırıldı.
Aniket Kulkarni

2
Şimdi .toDateMidnight ()
bgolson

2
ya endönce, startnegatif günler döndürüyor mu?
akhy

7
@akhyar: neden denemiyorsun?
Michael Borgwardt

86

şunları kullanabilirsiniz LocalDate:

Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

Efendim, bu yazıya referansla toDateMidnight()DateTime türündeki yöntem kullanımdan kaldırıldı.
Aniket Kulkarni

Neden kullanmak new LocalDate(date)üzerinde date.toLocalDate()?
SARose

9

tl; Dr.

java.time.temporal.ChronoUnit.DAYS.between( 
    earlier.toLocalDate(), 
    later.toLocalDate() 
)

…veya…

java.time.temporal.ChronoUnit.HOURS.between( 
    earlier.truncatedTo( ChronoUnit.HOURS )  , 
    later.truncatedTo( ChronoUnit.HOURS ) 
)

java.time

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

Joda-Time eşdeğer DateTimeolduğunu ZonedDateTime.

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

Görünüşe göre günleri tarihe göre saymak istiyorsunuz, yani günün saatini yok saymak istiyorsunuz. Örneğin, gece yarısından bir dakika önce başlamak ve gece yarısından bir dakika sonra sona ermek tek bir günle sonuçlanmalıdır. Bu davranışa, bir ayıklamak LocalDate, hesabınızla ilgili ZonedDateTime. LocalDateSınıf zaman günün-ve saat dilimi bulunmayan olmadan tarih salt değerini temsil eder.

LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;

ChronoUnitGeçen günleri veya diğer birimleri hesaplamak için numaralandırmayı kullanın .

long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;

truncate

Altmış dakikalık zaman aralığı olarak tam saat yerine saatin delta'sı ile ilgileniyorsanız bu sayımı yapmanın daha genel bir yolunu sormak için truncatedToyöntemi kullanın .

Aynı gün 14:45 - 15:12 örnekleriniz.

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );

long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );

1

Bu günlerce çalışmaz. Bu durumda toLocalDate () öğesini kullanın.


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 üzeri ile 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 .

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 .


TL; kesmeyi kullanan günler için DR, kabul edilen cevapta ayrıntılı olarak açıklanan hataya avlanır, yani gün başlangıcı saat 1'de olduğunda tek tek kapalıdır. Daha sonra verdiğiniz doğru cevabı, toLocalDate kullanarak kullanmak için güncelledim.
Alice Purcell

2

Kabul edilen cevap, LocalDateçok fazla veri okuyorsanız oldukça pahalı olan iki nesne oluşturur . Bunu kullanıyorum:

  public static int getDaysBetween(DateTime earlier, DateTime later)
  {
    return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
  }

Arayarak getMillis()mevcut değişkenleri kullanırsınız.
MILLISECONDS.toDays()daha sonra basit bir aritmetik hesaplama kullanır, herhangi bir nesne oluşturmaz.


1
Bu Yanıt, yalnızca 'günler' tanımınızın saat dilimlerine ve tarihlere bakılmaksızın tam olarak 24 saat uzunluğunda olması durumunda işe yarar. Öyleyse, bu yaklaşımı kullanın. Değilse, saat dilimlerini ele alan diğer yanıtlara bakın.
Basil Bourque

@BasilBourque, haklısın, yine de, aritmetik hesaplamaya dayalı bir çözüm için gitmek yerine daha sonra her yöntem çağrısı için pahalı nesneler inşa etmek, bir web sayfasından bir girdi okuyorsanız, bu tür hesaplamalar için orada birçok lezzet var, Tamam olabilir, ancak yüz binlerce satır içeren bir günlük dosyası
işliyorsanız

1
Döngünüz sıcaksa Java nesne ayırmayı optimize eder. Bkz. Docs.oracle.com/javase/7/docs/technotes/guides/vm/…
Alice Purcell

1

java.time.Period

Günleri saymak için java.time.Periodsınıfı kullanın .

Java 8 farkı hesaplayarak kullanarak daha sezgisel olduğundan LocalDate, LocalDateTimeiki tarihleri temsil etmek

    LocalDate now = LocalDate.now();
    LocalDate inputDate = LocalDate.of(2018, 11, 28);

    Period period = Period.between( inputDate, now);
    int diff = period.getDays();
    System.out.println("diff = " + diff);

0
DateTime  dt  = new DateTime(laterDate);        

DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());

System.out.println("No of days : " + newDate.getDayOfYear() - 1 );    

-11
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}

1
soru özellikle joda-time'ı arıyor.
kapad
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.