【问题标题】:Java, get days between two datesJava,获取两个日期之间的天数
【发布时间】:2015-09-04 02:25:18
【问题描述】:

在java中,我想获取两个日期之间的天数,不包括这两个日期。

例如:

如果第一个日期 = 11 November 2011 而第二个日期 = 13 November 2011 那么应该是1

这是我正在使用但不起作用的代码(secondDatefirstDateCalendar 对象):

long diff=secondDate.getTimeInMillis()-firstDate.getTimeInMillis();
float day_count=(float)diff / (24 * 60 * 60 * 1000);
daysCount.setText((int)day_count+"");                    

我什至尝试对结果进行四舍五入,但没有帮助。

如何获取 java 中日期之间的天数,不包括日期本身?

【问题讨论】:

  • 您在计算之前是否对日期进行了标准化?我的意思是你必须清除字段 HOUR_OF_DAY、MINUTE、SECOND 和 MILLISEC。
  • @slkorolev:哦...我真的不知道。让我再试一次。

标签: java date


【解决方案1】:

我刚刚在 SDK 8 (Android 2.2) 上测试了以下代码 sn-p:

Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();

date1.clear();
date1.set(
   datePicker1.getYear(),
   datePicker1.getMonth(),
   datePicker1.getDayOfMonth());
date2.clear();
date2.set(
   datePicker2.getYear(),
   datePicker2.getMonth(),
   datePicker2.getDayOfMonth());

long diff = date2.getTimeInMillis() - date1.getTimeInMillis();

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

textView.setText(Long.toString(diff) + " " + (int) dayCount);

它完美运行,在两种情况下(2011 年 11 月 10 日 - 2011 年 11 月 8 日)和(2011 年 11 月 13 日 - 2011 年 11 月 11 日)都给出 dayCount = 2.0

【讨论】:

  • 两个注意事项: 1. 不要使用浮点数将毫秒转换为天。 2. 要从计算中排除这两天,请从dayCount 中减去 1。
  • @Aaron:感谢您的评论,我同意。我认为原始问题的原因不在计算范围内,而是日历初始化。
  • 那里的 datePicker1 是什么?以及如何将我的日历对象与此代码一起使用??
  • @Hiral:dattePicker1 和 2 只是我的测试应用程序中的复合组件。它们存储输入日期的年、月和日。其实sn-p的重点是先清除所有的日期字段,然后只设置年月日:`date1.clear(); date1.set(year, month, dayOfMonth);`
  • 当时区考虑夏令时时失败,例如中部时间的“2013 年 3 月 10 日”与“2013 年 3 月 12 日”。
【解决方案2】:

获取 java.util.Dates 之间的天数,忽略夏令时

快速而肮脏的黑客攻击:

public int get_days_between_dates(Date date1, Date date2)
{       
    //if date2 is more in the future than date1 then the result will be negative
    //if date1 is more in the future than date2 then the result will be positive.

    return (int)((date2.getTime() - date1.getTime()) / (1000*60*60*24l));
}

此功能将在 99.99% 的时间内有效,除非稍后在闰秒、夏令时、时区更改闰年等边缘情况下让您感到惊讶。如果您可以接受计算偶尔会延迟 1(或 2)小时,这就足够了。

获取日期之间的天数,考虑闰秒、夏令时、时区等

如果你问这个问题,你需要打自己一巴掌。两个日期至少相隔 1 天是什么意思?这很令人困惑。如果一个日期是一个时区的午夜,而另一个日期是另一个时区的凌晨 1 点怎么办?根据你的解释,答案是 1 和 0。

您认为您可以强制将您传递给上述函数的日期作为通用时间格式,这将解决您的一些问题。但是,您只需将问题重新定位为如何将本地时间转换为通用时间。从您的时区到世界时的逻辑转换可能不是直观的。在某些情况下,当传入的日期明显相隔两天时,您会得到一个天差。

你认为你能应付吗?世界上有一些延迟的日历系统,它们根据收获季节和安装的政治统治者不断变化。如果您想将他们的时间转换为 UTC,java.util.Date 会在最糟糕的时刻让您失望。

如果您需要计算日期之间的天数并且一切都正确至关重要,您需要获取一个名为 Joda Time 的外部库:(他们已经为您处理了所有细节,因此您可以保持幸福不知道):http://joda-time.sourceforge.net/index.html

【讨论】:

  • +1 用于建议 Joda Time,理想情况下,这可能是您答案的第一句话。请注意,在大约 25% 的情况下,您的“快速而肮脏的 hack”将在一整天内完成,而不仅仅是 1 或 2 小时;即day2 在夏令时出现而day1 没有出现的情况。因此,它不会像您声称的那样“在 99.99% 的时间内工作”。
  • 如果您不想要负值,请在其中添加一个 Math.abs(diff)。
  • 我还会添加一个 Math.round(diff) 以确保您不会降低值。
  • 我知道它很旧,但是,Java 的 Calendar 类不能照顾它?
【解决方案3】:
  1. 不要使用浮点数进行整数计算。

  2. 您确定日期是天数吗? Date 类型的精度为毫秒。因此,您需要做的第一件事是将日期四舍五入到没有小时的日期。示例:从23:30 2011-11-0100:30 2011-11-02 仅一小时,但两个日期在不同的日期。

【讨论】:

  • 在计算天数之前,我将这两个日期的 HOUR_OF_DAY、MINUTE、SECOND 和 MILLISEC 字段设置为 0。是否正常或其他任何会导致问题?
  • 这应该可以解决问题。如果这不起作用,您应该会在 dayCount 中看到分数。
【解决方案4】:

如果您只打算处理 1900 年到 2100 年之间的日期,可以通过一个简单的计算来计算自 1900 年以来的天数:

public static int daysSince1900(Date date) {
    Calendar c = new GregorianCalendar();
    c.setTime(date);

    int year = c.get(Calendar.YEAR);
    if (year < 1900 || year > 2099) {
        throw new IllegalArgumentException("daysSince1900 - Date must be between 1900 and 2099");
    }
    year -= 1900;
    int month = c.get(Calendar.MONTH) + 1;
    int days = c.get(Calendar.DAY_OF_MONTH);

    if (month < 3) {
        month += 12;
        year--;
    }
    int yearDays = (int) (year * 365.25);
    int monthDays = (int) ((month + 1) * 30.61);

    return (yearDays + monthDays + days - 63);
}

因此,要获得两个日期之间的天数差异,您需要计算它们自 1900 年以来的天数并计算差异。我们的 daysBetween 方法如下所示:

public static Integer getDaysBetween(Date date1, Date date2) {
    if (date1 == null || date2 == null) {
        return null;
    }

    int days1 = daysSince1900(date1);
    int days2 = daysSince1900(date2);

    if (days1 < days2) {
        return days2 - days1;
    } else {
        return days1 - days2;
    }
}

在您的情况下,您需要减去额外的一天(如果天数不相等)。

不要问我这个计算是从哪里来的,因为我们从 90 年代初就开始使用它。

【讨论】:

    【解决方案5】:

    我有两个建议:

    1. 确保您的float day_count 计算正确

      float day_count = ((float)diff) / (24f * 60f * 60f * 1000f);

    2. 如果是舍入错误,请尝试使用floor方法

      daysCount.setText("" + (int)Math.floor(day_count));

    【讨论】:

    • 我应该按照 skorolev 的建议清除 HOUR_OF_DAY、MINUTE、SECOND 和 MILLISEC 字段吗?或者我可以照原样使用?
    • @Hiral 我认为这种方法没有必要。不过我还没有测试过。
    • 我已经测试了这两个选项,有和没有设置这些字段,但没有成功!无论如何,感谢您的回复!
    • @Hiral 你能在你设置firstDatesecondDate 的地方发布代码吗?
    • 实际上我正在使用 NumberPickerDialog,它给了我相应的日期。它工作得非常好。设置日期没有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多