用Java计算两个日期之间的天数

Posted

技术标签:

【中文标题】用Java计算两个日期之间的天数【英文标题】:Calculating days between two dates with Java 【发布时间】:2013-12-08 13:19:44 【问题描述】:

我想要一个计算两个日期之间天数的 Java 程序。

    输入第一个日期(德语表示法;带空格:“dd mm yyyy”) 输入第二个日期。 程序应计算两个日期之间的天数。

如何包含闰年和夏令时?

我的代码:

import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;

public class NewDateDifference 

    public static void main(String[] args) 

        System.out.print("Insert first date: ");
        Scanner s = new Scanner(System.in);
        String[] eingabe1 = new String[3];

        while (s.hasNext()) 
            int i = 0;
            insert1[i] = s.next();
            if (!s.hasNext()) 
                s.close();
                break;
            
            i++;
        

        System.out.print("Insert second date: ");
        Scanner t = new Scanner(System.in);
        String[] insert2 = new String[3];

        while (t.hasNext()) 
            int i = 0;
            insert2[i] = t.next();
            if (!t.hasNext()) 
                t.close();
                break;
            
            i++;
        

        Calendar cal = Calendar.getInstance();

        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(insert1[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(insert1[1]));
        cal.set(Calendar.YEAR, Integer.parseInt(insert1[2]));
        Date firstDate = cal.getTime();

        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(insert2[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(insert2[1]));
        cal.set(Calendar.YEAR, Integer.parseInt(insert2[2]));
        Date secondDate = cal.getTime();


        long diff = secondDate.getTime() - firstDate.getTime();

        System.out.println ("Days: " + diff / 1000 / 60 / 60 / 24);
    

【问题讨论】:

什么不起作用?它崩溃了吗?是不是给你错误的数字? 数组的声明在哪里:insert1? insert1 = eingabe1 德语 :) @peter.petrov 啊,我明白了! 我认为他对mmMM 有问题:P 【参考方案1】:

更新: 2013 年的原始答案现已过时,因为某些类已被替换。这样做的新方法是使用新的java.time 类。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";

try 
    LocalDateTime date1 = LocalDate.parse(inputString1, dtf);
    LocalDateTime date2 = LocalDate.parse(inputString2, dtf);
    long daysBetween = Duration.between(date1, date2).toDays();
    System.out.println ("Days: " + daysBetween);
 catch (ParseException e) 
    e.printStackTrace();

请注意,此解决方案将给出实际 24 小时天数,而不是日历天数。对于后者,使用

long daysBetween = ChronoUnit.DAYS.between(date1, date2)

原始答案(从 Java 8 开始已过时)

您正在使用您的字符串进行一些不必要的转换。它有一个 SimpleDateFormat 类 - 试试这个:

SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";

try 
    Date date1 = myFormat.parse(inputString1);
    Date date2 = myFormat.parse(inputString2);
    long diff = date2.getTime() - date1.getTime();
    System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
 catch (ParseException e) 
    e.printStackTrace();

编辑:由于已经讨论过这段代码的正确性:它确实考虑了闰年。但是,TimeUnit.DAYS.convert 函数会丢失精度,因为毫秒会转换为天(有关更多信息,请参阅链接文档)。如果这是一个问题,diff也可以手动转换:

float days = (diff / (1000*60*60*24));

请注意,这是一个float 值,不一定是int

【讨论】:

这是一个糟糕的实现,没有正确考虑闰年。 TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)); @GroovyEd 从我测试的结果来看,这段代码似乎对闰年没有问题。请注意 TimeUnit.Days.convert() 将忽略剩余的单位,例如将 999 毫秒转换为秒的结果为 0。这意味着如果您使用 new Date() 作为 Date 对象之一,您可能会少一天,所以要小心 它也适用于闰年。检查这个String inputString1 = "28 2 2016"; String inputString2 = "1 3 2016"; ans: 2 我相信这在闰年可以正常工作,但它会扰乱夏令时。如果您的区域设置有夏令时,那么每年都有一天有 23 小时,一天有 25 小时。此解决方案错误地假设每天有 24 小时。因此,对于从非夏令时开始到夏令时结束的任何时间段,它都会给出错误的答案。不要使用此解决方案 - 有更好的方法。【参考方案2】:

最简单的方法:

public static long getDifferenceDays(Date d1, Date d2) 
    long diff = d2.getTime() - d1.getTime();
    return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);

【讨论】:

嗯,基本上这与current best answer 相同,尽管这个答案提供了它作为一个函数。 请注意,仅当两个日期之间的时间间隔大于 24 小时时才计算(从代码中非常明显),因此 getDifferenceDays(11PM, 4 AM nextday) == 0 此实现将最后一天作为今天。例如,如果我使用 d1 = 今天和 d2 = 昨天运行程序,则返回 0 天.. @Nav 那是因为六月有 30 天。 这个答案不正确。它不能正确处理夏令时。如果您想要正确的结果,请不要使用它。【参考方案3】:

在 Java 8 中,您可以通过使用 LocalDateDateTimeFormatter 来完成此操作。来自LocalDate的Javadoc:

LocalDate 是表示日期的不可变日期时间对象, 通常被视为年-月-日。

并且可以使用DateTimeFormatter 构造模式。这是Javadoc,以及我使用的相关模式字符:

符号 - 含义 - 演示文稿 - 示例

y - 年代 - year - 2004 年; 04

M/L - 一年中的月份 - 数字/文本 - 7; 07;七月; 七月; J

d - 一个月中的某天 - 数字 - 10

示例如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class Java8DateExample 
    public static void main(String[] args) throws IOException 
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MM yyyy");
        final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        final String firstInput = reader.readLine();
        final String secondInput = reader.readLine();
        final LocalDate firstDate = LocalDate.parse(firstInput, formatter);
        final LocalDate secondDate = LocalDate.parse(secondInput, formatter);
        final long days = ChronoUnit.DAYS.between(firstDate, secondDate);
        System.out.println("Days between: " + days);
    

最近的输入/输出示例:

23 01 1997
27 04 1997
Days between: 94

最近的优先:

27 04 1997
23 01 1997
Days between: -94

嗯,你可以用一种更简单的方法来做:

public static long betweenDates(Date firstDate, Date secondDate) throws IOException

    return ChronoUnit.DAYS.between(firstDate.toInstant(), secondDate.toInstant());

【讨论】:

很好的例子。这会自动考虑闰年。如果您检查了 1991 年和 1992 年(闰年),则计算正确。完美! 很好地使用标准库。 这应该是当前接受的答案。标准库的使用和会计闰年和夏令时不会成为问题。 这是当前/现代的答案(其他已过时)。它还考虑了夏令时 (DST)。要在 Java 6 或 7 上使用,请获取 ThreeTen Backport。在非新 android ThreeTenABP. 不考虑夏令时【参考方案4】:

夏令时到来时,大多数/所有答案都给我们带来了问题。这是我们所有日期的工作解决方案,不使用 JodaTime。它利用日历对象:

public static int daysBetween(Calendar day1, Calendar day2)
    Calendar dayOne = (Calendar) day1.clone(),
            dayTwo = (Calendar) day2.clone();

    if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) 
        return Math.abs(dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR));
     else 
        if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) 
            //swap them
            Calendar temp = dayOne;
            dayOne = dayTwo;
            dayTwo = temp;
        
        int extraDays = 0;

        int dayOneOriginalYearDays = dayOne.get(Calendar.DAY_OF_YEAR);

        while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) 
            dayOne.add(Calendar.YEAR, -1);
            // getActualMaximum() important for leap years
            extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
        

        return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOneOriginalYearDays ;
    

【讨论】:

很好地处理夏令时切换 +1 作为答案,但是,想要补充一点,我们需要 Calendar dayOne = (Calendar) day1.clone(), dayTwo = (Calendar) day2.clone(); 行,因为它们确保原始日历值不会被覆盖。我删除了这些行,认为它们是多余的,并且浪费了一个小时,因为我的原始对象的值正在从这个函数内部被覆盖。 不要忘记 Calendar 类中的 Month 值是从 0 开始的。 calendar.set(2015, 11, 30, 0, 00, 00);实际上意味着 2015 年 12 月 30 日【参考方案5】:

最好的方法,它转换为字符串作为奖励;)

protected void onCreate(Bundle savedInstanceState) 

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try 
        //Dates to compare
        String CurrentDate=  "09/24/2015";
        String FinalDate=  "09/26/2015";

        Date date1;
        Date date2;

        SimpleDateFormat dates = new SimpleDateFormat("MM/dd/yyyy");

        //Setting dates
        date1 = dates.parse(CurrentDate);
        date2 = dates.parse(FinalDate);

        //Comparing dates
        long difference = Math.abs(date1.getTime() - date2.getTime());
        long differenceDates = difference / (24 * 60 * 60 * 1000);

        //Convert long to String
        String dayDifference = Long.toString(differenceDates);

        Log.e("HERE","HERE: " + dayDifference);
    
    catch (Exception exception) 
        Log.e("DIDN'T WORK", "exception " + exception);
    

【讨论】:

抛出异常的可能性有多大? 请注意,这在闰年不起作用。例如,从“02/15/2020”到“04/02/2020”是 47 天。这个逻辑会得出 46。【参考方案6】:

用途:

public int getDifferenceDays(Date d1, Date d2) 
    int daysdiff = 0;
    long diff = d2.getTime() - d1.getTime();
    long diffDays = diff / (24 * 60 * 60 * 1000) + 1;
    daysdiff = (int) diffDays;
    return daysdiff;

【讨论】:

这算不算闰年和夏令时? @MaxAlexanderHanna 它正确地考虑了闰年,但不考虑夏令时。仅当一段时间在非夏令时开始但在夏令时结束时,它才会给出正确答案。在所有其他情况下,它都减一。 @saidesh_kilaru 什么是“+1”?我认为你应该删除它。 我遇到了一个问题,即转换为 INT 会导致 4,转换为 float 会导致 4.9,所以这不是我真正想要的;可能不够清楚地描述了 date1 在 23:59 和 date2 在 00:01 的情况以及预期的结果。【参考方案7】:

Java 日期库是出了名的损坏。我建议使用Joda Time。它将为您处理闰年、时区等。

最小的工作示例:

import java.util.Scanner;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class DateTestCase 

    public static void main(String[] args) 

        System.out.print("Insert first date: ");
        Scanner s = new Scanner(System.in);
        String firstdate = s.nextLine();
        System.out.print("Insert second date: ");
        String seconddate = s.nextLine();

        // Formatter
        DateTimeFormatter dateStringFormat = DateTimeFormat
                .forPattern("dd MM yyyy");
        DateTime firstTime = dateStringFormat.parseDateTime(firstdate);
        DateTime secondTime = dateStringFormat.parseDateTime(seconddate);
        int days = Days.daysBetween(new LocalDate(firstTime),
                                    new LocalDate(secondTime)).getDays();
        System.out.println("Days between the two dates " + days);
    

【讨论】:

这个答案可以通过几种方式进行改进。 (a) 指定时区而不是依赖 JVM 的默认值。因此,在创建 DateTimeFormatter 时,添加对 withZone( DateTimeZone.forID( "Europe/Berlin" ) ) 的调用。 (b) 为什么在daysBetween 调用中使用LocalDate?只需传递 DateTime 对象(firstTime、secondTime)。全天,请致电withTimeAtStartOfDays。 (c) 我会使用变量名firstDateTime 而不是firstTime 以避免日期、时间和日期时间对象之间的歧义。 (d) 添加一些 try-catch 来处理不符合我们预期格式的错误数据输入。【参考方案8】:
String dateStart = "01/14/2015 08:29:58";
String dateStop = "01/15/2015 11:31:48";

//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

Date d1 = null;
Date d2 = null;

d1 = format.parse(dateStart);
d2 = format.parse(dateStop);

//in milliseconds
long diff = d2.getTime() - d1.getTime();

long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);

System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");

【讨论】:

【参考方案9】:

当我运行你的程序时,它甚至没有得到我 到我可以输入第二个日期的程度。

这更简单,更不容易出错。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test001 

    public static void main(String[] args) throws Exception 

        BufferedReader br = null;

        br = new BufferedReader(new InputStreamReader(System.in));
        SimpleDateFormat sdf = new SimpleDateFormat("dd MM yyyy");

        System.out.println("Insert first date : ");
        Date dt1 = sdf.parse(br.readLine().trim());

        System.out.println("Insert second date : ");
        Date dt2 = sdf.parse(br.readLine().trim());

        long diff = dt2.getTime() - dt1.getTime();

        System.out.println("Days: " + diff / 1000L / 60L / 60L / 24L);

        if (br != null) 
            br.close();
        
    

【讨论】:

【参考方案10】:

我们可以使用 LocalDate 和 ChronoUnit java 库,下面的代码运行良好。 日期格式应为 yyyy-MM-dd。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
class Solution 
    public int daysBetweenDates(String date1, String date2) 
        LocalDate dt1 = LocalDate.parse(date1);
        LocalDate dt2= LocalDate.parse(date2);

        long diffDays = ChronoUnit.DAYS.between(dt1, dt2);

        return Math.abs((int)diffDays);
    

【讨论】:

感谢您的贡献。我相信这个好建议已经在 mkobit 的回答中提出了。 解决时来到这里:leetcode.com/problems/number-of-days-between-two-dates【参考方案11】:
// date format, it will be like "2015-01-01"
private static final String DATE_FORMAT = "yyyy-MM-dd";

// convert a string to java.util.Date
public static Date convertStringToJavaDate(String date)
        throws ParseException 
    DateFormat dataFormat = new SimpleDateFormat(DATE_FORMAT);
    return dataFormat.parse(date);


// plus days to a date
public static Date plusJavaDays(Date date, int days) 
    // convert to jata-time
    DateTime fromDate = new DateTime(date);
    DateTime toDate = fromDate.plusDays(days);
    // convert back to java.util.Date
    return toDate.toDate();


// return a list of dates between the fromDate and toDate
public static List<Date> getDatesBetween(Date fromDate, Date toDate) 
    List<Date> dates = new ArrayList<Date>(0);
    Date date = fromDate;
    while (date.before(toDate) || date.equals(toDate)) 
        dates.add(date);
        date = plusJavaDays(date, 1);
    
    return dates;

【讨论】:

【参考方案12】:

只想获得几天(没有时间)可以使用 ChronoUnit

ChronoUnit.DAYS.between(date1.toLocalDate(), date2.toLocalDate());

【讨论】:

【参考方案13】:

以下内容非常适合我:

public int daysBetween(LocalDate later, LocalDate before) 
        SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
        int daysBetween = 0;
        try 
            Date dateBefore = myFormat.parse(localDateToString(before));
            Date dateAfter = myFormat.parse(localDateToString(later));
            long difference = dateAfter.getTime() - dateBefore.getTime();
            daysBetween = (int) (difference / (1000 * 60 * 60 * 24));
         catch (Exception e) 
            e.printStackTrace();
        
        return daysBetween;
    

    public String localDateToString(LocalDate date) 
        DateTimeFormatter myFormat = DateTimeFormatter.ofPattern("dd MM yyyy");
        return date.format(myFormat).toString();
    

【讨论】:

【参考方案14】:
public class TestCode 

    public static void main(String[] args)         
        String date1 = "23-04-2021";
        String date2 = "24-05-2021";
        System.out.println("NDays: " + nDays_Between_Dates(date1, date2));      
    
    
    public static int nDays_Between_Dates(String date1, String date2) 
        int diffDays = 0;
        try 
            SimpleDateFormat dates = new SimpleDateFormat("dd-MM-yyyy");
            Date startDate = dates.parse(date1);
            Date endDate = dates.parse(date2);
            long diff = endDate.getTime() - startDate.getTime();
            diffDays = (int) (diff / (24 * 60 * 60 * 1000));            
         catch (ParseException e) 
            e.printStackTrace();
        
        return Math.abs(diffDays);
    

输出:NDays:31

【讨论】:

【参考方案15】:

我正在使用这个。

              try 
                    Date dateBefore = myFormat.parse(02-03-2022);
                    Date dateAfter = myFormat.parse(27-02-2022);
                    long difference = dateAfter.getTime() - dateBefore.getTime();
                    float daysBetween = (difference / (1000*60*60*24));
                    int count = Math.round(daysBetween);
                    Log.e("DateCount", "onClick: DateCount_Float: "+daysBetween );
                    Log.e("DateCount", "onClick: DateCount_Int: "+count);

                 catch (Exception e) 
                    e.printStackTrace();
                

日志输出:

DateCount: onClick: DateCount_Float: 3.0

DateCount: onClick: DateCount_INT: 3

【讨论】:

以上是关于用Java计算两个日期之间的天数的主要内容,如果未能解决你的问题,请参考以下文章

java怎样计算两个日期之间的秒数

java中计算两个日期之间天数的程序设计。

java计算两个日期之间的天数

java中计算两个日期之间差的天数

java中计算两个日期之间差的天数

在 Java 8 中计算两个日期之间的天数