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


150

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

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

如何包含leap年和夏季?

我的代码:

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

什么不起作用?它崩溃了吗?它给您错误的数字吗?
jens108

数组的声明在哪里:insert1?
Rhys

1
insert1 = eingabe1德语:)
peter.petrov 2013年

@ peter.petrov啊,我明白了!
Rhys

我认为他与mmand MM:P
Sage

Answers:


229

更新:由于某些类已被替换,因此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();
}

编辑:由于已经有一些有关此代码的正确性的讨论:它确实照顾care年。但是,该TimeUnit.DAYS.convert函数会失去精度,因为毫秒数已转换为天数(有关更多信息,请参见链接的文档)。如果有问题,diff也可以手动转换:

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

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


40
这是一个糟糕的实现,无法正确说明leap年。
Groovy Ed

3
TimeUnit.DAYS.convert(diff,TimeUnit.MILLISECONDS)); <3
Guihgo '16

3
@GroovyEd从我的测试看来,这段代码对于leap年没有问题。请注意,TimeUnit.Days.convert()将忽略剩余的单位,例如,将999毫秒转换为秒将得出0。这意味着,如果将new Date()用作Date对象之一,则可能会少一天,所以请小心
Klitos G.

3
它也适用于leap年。检查以下String inputString1 = "28 2 2016"; String inputString2 = "1 3 2016";答案:2
Rohit Gaikwad's

10
我认为这在leap年中可以正常使用,但是却浪费了夏令时。如果您的语言环境具有夏令时,那么每年会有一天的时间为23小时,有一天的时间为25小时。该解决方案错误地假设每天都有24小时。因此,对于从非夏令时开始到夏令时结束的任何时期,它都会给出错误的答案。请勿使用此解决方案-有更好的方法。
达伍德·伊本·卡里姆

100

最简单的方法:

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

7
嗯,基本上,这与当前的最佳答案相同,尽管此答案提供了它的功能。
Andrew T.

16
请注意,仅当两个日期之间的时间间隔大于24小时(从代码中非常明显)时,此计数才算在内,因此getDifferenceDays(11PM, 4 AM nextday) == 0
ReDetection

1
此实现将最后一天作为今天。举例来说,如果我有D1 =今天和d2 =昨天,返回0天运行一次的程序..
karvoynistas

1
@Nav是因为六月有30天。
达伍德·伊本·卡里姆

1
这个答案是不正确的。它不能正确处理夏令时。如果您想要正确的结果,请不要使用它。
达伍德·伊本·卡里姆

89

在Java 8中,您可以使用LocalDate和来完成此操作DateTimeFormatter。从的JavadocLocalDate

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

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

符号 -含义- 演示 -示例

ÿ年的时代- - - 2004年; 04

M / L-年月- 数字/文本 -7; 07; 七月 七月; Ĵ

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

4
很好的例子。这将自动计算leap年。如果检查了1991年和1992年(le年),则计算正确。完善!
woahguy

大量使用标准库。
dieresys

这应该是当前接受的答案。标准库的使用以及accounts年和夏令时的考虑将不成问题。
Pehmolelu

3
这是当前/现代的答案(其他答案已过时)。它还考虑了夏令时(DST)。要在Java 6或7上使用,请获取ThreeTen Backport。在全新的Android ThreeTenABP上
Ole VV

它没有考虑夏令时
Alex

63

当夏时制到来时,大多数/所有答案都给我们带来了问题。这是我们所有日期的工作解决方案,无需使用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 ;
    }
}

很好地处理夏令时切换
Ravi Sanwal15年

1
但是,答案的+1是要添加的,我们需要这些Calendar dayOne = (Calendar) day1.clone(), dayTwo = (Calendar) day2.clone();行,因为它们可以确保不覆盖原始日历值。我删除了这些行,以为它们多余,并浪费了一个小时,因为我原来的对象的值已从该函数内部被覆盖。
Rohan Kandwal

2
不要忘记,“日历类”中的“月”值基于0。calendar.set(2015,11,30,0,00,00); 实际上是指2015
德米特里(Dmitry)

20

最好的方法,它将奖金转换为String;)

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

引发异常的可能性是什么?
CoDe17年

请注意,这在leap年不起作用。例如,从“ 02/15/2020”到“ 04/02/2020”为47天。这个逻辑将拿出46
user1070304

11

用:

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

这说明leap年和夏时制吗?
马克斯·亚历山大·汉娜

1
@MaxAlexanderHanna可以正确解释leap年,但不能节省夏令时。仅在非夏令时期间开始但夏时制期间结束时,它才能给出正确的答案。在其他所有情况下,结果都是不一样的。
达伍德·伊本·卡里姆

1
@saidesh_kilaru什么是“ +1”?我认为您应该删除它。
艾丽莎

我有一个问题,强制转换为INT会导致4,而转换为float会导致4.9,所以这不是我真正想要的。可能不够清楚地描述date1在23:59和date2在00:01的情况以及预期结果。
EricG

10

Java日期库臭名昭著。我建议使用Joda Time。它将为您处理leap年,时区等。

最小的工作示例:

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

4
这个答案可以通过几种方式加以改进。(a)指定时区,而不要依赖JVM的默认时区。因此,当创建该DateTimeFormatter时,请添加一个调用withZone( DateTimeZone.forID( "Europe/Berlin" ) )。(b)为什么LocalDatedaysBetween通话中使用?只需传递DateTime对象(firstTime,secondTime)即可。整整一天,请致电withTimeAtStartOfDays。(c)我会使用变量名,firstDateTime而不是firstTime避免日期,时间和日期时间对象之间的歧义。(d)添加一些try-catch来处理与我们期望的格式不匹配的错误数据输入。
罗勒·布尔克

5
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.");

1

当我运行您的程序时,我什至无法输入第二个日期。

这更简单,错误更少。

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

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

0

我们可以使用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);
    }
}

4
感谢您的贡献。我相信mkobit的答案已经提出了这个好建议。
Ole VV
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.