如何正确计算2个日期之间的实际月数?

时间:2012-11-01 20:28:37

标签: java android date

我遵循方法getDiffDateMap来计算2个日期之间的差异,并返回分别代表毫秒,秒,分钟,小时,天,月和年的整数Map

public static Map<Integer, String> getDiffDateMap(String dateA, String dateB) {

    Calendar cal = Calendar.getInstance();      
    Map<Integer,String> out = new LinkedHashMap<Integer, String>();
    long timeInMillA = 0;
    long timeInMillB = 0;

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 

    Date convertedDateA;
    Date convertedDateB;



    try {
        convertedDateA = dateFormat.parse(dateA);           
        cal.setTime(convertedDateA);
        timeInMillA = cal.getTimeInMillis();


        convertedDateB = dateFormat.parse(dateB);           
        cal.setTime(convertedDateB);
        timeInMillB = cal.getTimeInMillis();

    } catch (ParseException e) {
        e.printStackTrace();
    } 

    long mili = timeInMillB - timeInMillA;
    long sec = mili/1000;
    long min = sec/60;
    long hour = min/60;
    long day = hour/24;
    long week = day/7;
    long month = day/31; // ????
    long year = month/12;

    out.put(7, mili + "");
    out.put(6, sec + "");
    out.put(5, min + "");
    out.put(4, hour + "");
    out.put(3, day + "");
    out.put(2, week + "");
    out.put(1, month + "");
    out.put(0, year + "");

    return out;
}

我的问题是从实际日期计算月份:

long month = day/31; // or 30

例如:

Map<Integer,String> out = getDiffInMillsec("2012-9-01 20:9:01", "2012-10-01 20:10:01");

    System.out.println(Arrays.asList(out)); 

我得到输出:[{7=2592060000, 6=2592060, 5=43201, 4=720, 3=30, 2=4, 1=0, 0=0}]其中1是月份数,它是0.因为差异只有30天。我需要添加什么流来解决这个问题?有什么建议吗?

5 个答案:

答案 0 :(得分:6)

  

我遵循方法getDiffDateMap计算2个日期之间的差异,并返回分别代表毫秒,秒,分钟,小时,天,月和年的整数映射。

不要重新发明轮子:)

Joda Time有代码可以执行所有这些以及更多操作。例如:

LocalDateTime start = ...;
LocalDateTime end = ...;
Period difference = new Period(start, end, PeriodType.yearMonthDayTime());
int months = difference.getMonths(); // etc

请注意,当您将不同的月份转换为毫秒数时,无法获得月数 - 因为月数将取决于开始/结束日期。 (30天可能是也可能不是一个月,例如......)

我强烈建议您在整个Java代码中使用Joda Time,而不是java.util.*。这是一个很多更好的API,并且希望很少 - 如果你需要编写自己的日期/时间处理代码。

答案 1 :(得分:4)

我建议使用JodaTime#Months

这具有以下功能:

    static Months   monthsBetween(ReadableInstant start, ReadableInstant end) 

创建一个月份,表示两个指定日期时间之间的整月数。

    static Months   monthsBetween(ReadablePartial start, ReadablePartial end) 

创建一个月份,表示两个指定的部分日期时间之间的整月数。

答案 2 :(得分:1)

我只想在Jon Skeet的帮助下结束我们之前谈过的所有内容,这是一个答案,我每个日期值使用JodaTimenew Period

import org.joda.time.LocalDateTime;
import org.joda.time.Period;
import org.joda.time.PeriodType;

....
    public static Map<Integer, String> getDateTimeDiffMap(String dateA, String dateB) {

    Calendar cal = Calendar.getInstance();
    Map<Integer,String> out = new LinkedHashMap<Integer, String>();

    long timeInMillA = 0;
    long timeInMillB = 0;

    SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); 

    Date convertedDateA;
    Date convertedDateB;

    try {
    convertedDateA = dateFormat.parse(dateA);           
    cal.setTime(convertedDateA);
    timeInMillA = cal.getTimeInMillis();


    convertedDateB = dateFormat.parse(dateB);           
    cal.setTime(convertedDateB);
    timeInMillB = cal.getTimeInMillis();

} catch (ParseException e) {
    e.printStackTrace();
} 


    LocalDateTime startA = new LocalDateTime(timeInMillA);
    LocalDateTime startB = new LocalDateTime(timeInMillB);

    Period difference = new Period(startA, startB, PeriodType.days());
    int day = difference.getDays();

    difference = new Period(startA, startB, PeriodType.months());
    int month = difference.getMonths();

    difference = new Period(startA, startB, PeriodType.years());
    int year = difference.getYears();

    difference = new Period(startA, startB, PeriodType.weeks());
    int week = difference.getWeeks();

    difference = new Period(startA, startB, PeriodType.hours());
    int hour = difference.getHours();

    difference = new Period(startA, startB, PeriodType.minutes());
    long min = difference.getMinutes();

    difference = new Period(startA, startB, PeriodType.seconds());
    long sec = difference.getSeconds();

    //difference = new Period(startA, startB, PeriodType.millis());
    long mili = timeInMillB - timeInMillA;  


    out.put(7, mili + "");
    out.put(6, sec + "");
    out.put(5, min + "");
    out.put(4, hour + "");
    out.put(3, day + "");
    out.put(2, week + "");
    out.put(1, month + "");
    out.put(0, year + "");      

    return out;
}

例如“01-09-2012 20:9:01”,“01-10-2012 20:9:01”我得到输出:

year=0;
month = 1;
day=30;
hour=720;
...

答案 3 :(得分:1)

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

另外,下面引用的是来自 home page of Joda-Time 的通知:

<块引用>

请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。

使用 java.time(现代日期时间 API)的解决方案:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getDiffDateMap("2012-9-01 20:9:01", "2012-10-01 20:10:01"));
    }

    public static Map<Integer, String> getDiffDateMap(String dateA, String dateB) {
        Map<Integer, String> out = new LinkedHashMap<Integer, String>();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
        LocalDateTime ldtA = LocalDateTime.parse(dateA, dtf);
        LocalDateTime ldtB = LocalDateTime.parse(dateB, dtf);

        out.put(7, String.valueOf(ChronoUnit.MILLIS.between(ldtA, ldtB)));
        out.put(6, String.valueOf(ChronoUnit.SECONDS.between(ldtA, ldtB)));
        out.put(5, String.valueOf(ChronoUnit.MINUTES.between(ldtA, ldtB)));
        out.put(4, String.valueOf(ChronoUnit.HOURS.between(ldtA, ldtB)));
        out.put(3, String.valueOf(ChronoUnit.DAYS.between(ldtA, ldtB)));
        out.put(2, String.valueOf(ChronoUnit.WEEKS.between(ldtA, ldtB)));
        out.put(1, String.valueOf(ChronoUnit.MONTHS.between(ldtA, ldtB)));
        out.put(0, String.valueOf(ChronoUnit.YEARS.between(ldtA, ldtB)));

        return out;
    }
}

输出:

{7=2592060000, 6=2592060, 5=43201, 4=720, 3=30, 2=4, 1=1, 0=0}

ONLINE DEMO

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 4 :(得分:0)

    try {
        String user = request.getParameter("uname");
        out.println(user); 
        String pass = request.getParameter("pass");
        out.println(pass);
        java.sql.Date sqlDate = new java.sql.Date(new java.util.Date().getTime());

        Class.forName( "com.mysql.jdbc.Driver" );
        Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/trans","root","root" ) ;
        Statement st = conn.createStatement(); 

        String sql = "insert into purch (cd,cust,dateof) values('" + user + "','" + pass + "', '" + sqlDate + "')";
        st.executeUpdate(sql);

        Date date = new Date();
        String modifiedDate= new SimpleDateFormat("-MM-").format(date);
        String dd = modifiedDate.toString();
        String da = "ai";
        out.println(dd);

        PreparedStatement statement = conn.prepareStatement("select * from purch where  dateof LIKE ? and cd = ?");    
        statement.setString(1,"%" + dd + "%");
        statement.setString(2,"" + da + "");
        ResultSet rs = statement.executeQuery();


        if(rs != null) {
        while(rs.next()) {
            out.println(rs.getString("cd"));
            out.println(rs.getString("cust"));
            out.println(rs.getString("dateof"));
        }
        }  
    }catch(Exception e) {
        System.out.println(e.toString());
    }