2

Ok, so I've created a function to show the number of days until a date in the future... It is correct until the amount of days is over 9 days.. if over it seems to show a random number of days... Please see my code below:

   public String daysTillExpire() {
        String daysLeft = "";
        int position = 0 ;
        String inputDateString = UIDM.get(position).date;
        Calendar calCurr = Calendar.getInstance();
        Calendar day = Calendar.getInstance();


        try {
            day.setTime(new SimpleDateFormat("dd-MM-yyyy").parse(inputDateString));

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

            if (day.after(calCurr)) {

                String noumberOfDays = "Days left: " + (day.get(Calendar.DAY_OF_MONTH) - (calCurr.get(Calendar.DAY_OF_MONTH)));

                daysLeft = UIDM.get(position).date + "\n(" + noumberOfDays+")" ;

            }

            else if (day.before(calCurr)) {
                daysLeft = "Key Expired";
            return daysLeft; }
        return daysLeft;
    }

UIDM is a data model containing info... String inputDateString = UIDM.get(position).date; returns the value 01-10-2018 23:59.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
astric mobiles
  • 468
  • 3
  • 14
  • What is "UIDM"? – Prashanth Verma Sep 12 '18 at 10:36
  • UIDM is a data model containing info... 'String inputDateString = UIDM.get(position).date; returns has the value '01-10-2018 23:59' – astric mobiles Sep 12 '18 at 10:41
  • 2
    As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Sep 12 '18 at 12:47
  • Ok, thank you for the recommendation, i'll look into it, – astric mobiles Sep 12 '18 at 12:52
  • 1
    FYI, the troublesome old date-time classes such as `java.util.Date`, `java.util.Calendar`, and `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. Most of the *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Sep 12 '18 at 21:13

4 Answers4

5

java.time

java.time, the modern Java date and time API, has methods for calculating the number of days between two dates. So don’t bother doing this calculation yourself. It’s error-prone.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu H:mm");
    String inputDateString = "01-10-2018 23:59";
    LocalDate today = LocalDate.now(ZoneId.of("Pacific/Auckland"));
    LocalDate expiration = LocalDate.parse(inputDateString, dateFormatter);
    if (expiration.isAfter(today)) {
        String numberOfDays = "Days left: " + ChronoUnit.DAYS.between(today, expiration);
        System.out.println(numberOfDays);
    }

Running this snippet just now (already September 13 in New Zealand) I got this output:

Days left: 18

Please substitute your correct time zone if it didn’t happen to be Pacific/Auckland.

The answer by LaVepe has already explained nicely and correctly what went wrong in your code, so I am not repeating that.

The date and time classes you were using — Calendar and SimpleDateFormat — are long outdated and were always poorly designed. There is a way to get Calendar to count days, 1 day at a time, but it’s not well suited for that. SimpleDateFormat is notorious for the trouble it has caused for many programmers. I recommend you avoid those classes altogether and use java.time instead.

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

Note that Calendar.DAY_OF_MONTH returns the day of the month between 1 and 31

so it will calculate difference between two days (number between 1 and 31) as if they were in the same month

I would suggest to rather use timestamps and then convert the result from millis to number of days like this:

long oneDay = 24 * 60 * 60 * 1000;  // in milliseconds
long diff = day.getTime().getTime() - calCurr.getTime().getTime();
long numberOfDays = diff / oneDay;

then you can change it to String with Long.toString(numberOfDays)

LaVepe
  • 1,137
  • 1
  • 8
  • 12
  • Worked perfectly... Thank you very much for explaining how Calendar.DAY_OF_MONTH works - Much appreciated. – astric mobiles Sep 12 '18 at 11:25
  • 1
    Good explanation. Your suggested solution is low-level. I’d prefer to use a library methods for calculating the difference. – Ole V.V. Sep 12 '18 at 12:47
  • 2
    This Answer is **incorrect**. Days are ***not* always 24 hours**. They can be 23, 23.5, 24, 25, or many other numbers of hours long. – Basil Bourque Sep 12 '18 at 21:14
  • @BasilBourque is right. If you measure the delta in days between a date in winter time and a date in summer time then the suggested code will break. – Meno Hochschild Sep 13 '18 at 08:55
1

Try this method

/**
         *  
         * @param token
         * @param date1 present date
         * @param date2 future date 
         * @return diff
         */
        public float dateDiff(String token,Date date1,Date date2){

            float diff=0;
            //different date might have different offset
            Calendar cal1=Calendar.getInstance(); 
            Calendar cal2=Calendar.getInstance();
            cal1.setTime(date1);          
            long ldate1 = date1.getTime() + cal1.get(Calendar.ZONE_OFFSET) + cal1.get(Calendar.DST_OFFSET);

            if(date2==null)
                cal2.setTime(new Date());
            else
                cal2.setTime(date2);
            long ldate2 = date2.getTime() + cal2.get(Calendar.ZONE_OFFSET) + cal2.get(Calendar.DST_OFFSET);

            // Use integer calculation, truncate the decimals
            int hr1   = (int)(ldate1/3600000); //60*60*1000
            int hr2   = (int)(ldate2/3600000);

            int days1 = hr1/24;
            int days2 = hr2/24;
            int dateDiff  = days2 - days1;
            int yearDiff  = cal2.get(Calendar.YEAR) - cal1.get(Calendar.YEAR); 
            float monthDiff = yearDiff * 12 + cal2.get(Calendar.MONTH) - cal1.get(Calendar.MONTH);
            System.out.println("monthDiff 1" +monthDiff);
            System.out.println(" days:  ;;;;222  "+dateDiff);
            float fbm = dateDiff ; 

            fbm = (float) MasterLibraryFunction.doubRound(fbm /30,2) ;

                if(token.equals("d"))
            {
                diff=dateDiff;
                System.out.println(" days:  ;;;;  "+dateDiff);
            }
            else if(token.equals("m"))
            {
                //diff= monthDiff;
                diff =fbm;
                System.out.println(" diff ---------->:  ;;;;  "+fbm);

            }

    /*******day wise diff *******/      


            return diff;
        }



/**
     * @category Decimal point round
     * @param  val
     * @param  places
     * @return Rounded Value to given place
     */
    public static double doubRound(double val, int places) {
        long factor = (long)Math.pow(10,places);
        val = val * factor;
        long tmp = Math.round(val);
        return (double)tmp / factor;
    }
1

To get interval days between two days, you could do like this:

public long daysTillExpire() {

    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
    String dateInString = "01-10-2018 23:59";
    Date date = null;
    try {
        date = sdf.parse(dateInString);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    Calendar expiredCalendar = Calendar.getInstance();
    expiredCalendar.setTime(date);

    long msDiff = expiredCalendar.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
    long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff); 

    return daysDiff;
}

above function is tested successfully, modify it according to your requirment.

navylover
  • 12,383
  • 5
  • 28
  • 41