makis.k
makis.k

Reputation: 462

Android calendar object from string

I want to make a function for my android app, where i pass 3 variables

  1. From (string representing a date)
  2. To (string representing a date)
  3. unit (integer)

What the result should be, is the difference of these two date in weeks, or days or years depending on unit. This is my code:

 private int datesDifference(String from, String to, int unit){
   Calendar from_date = Calendar.getInstance();
   Calendar to_date = Calendar.getInstance();
   DebugLogger.debug("From date = "+from+" to date = "+to);

   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd", Locale.getDefault());
   try {
       from_date.setTime(sdf.parse(from));
       to_date.setTime(sdf.parse(to));
   } catch (ParseException e) {
       e.printStackTrace();
   }

   int from_year = from_date.get(Calendar.YEAR);
   int from_month = from_date.get(Calendar.MONTH)+1;
   int from_day = from_date.get(Calendar.DAY_OF_MONTH);
   DebugLogger.debug("from_year "+from_year+" from month "+from_month+" from day "+from_day);

   int to_year = to_date.get(Calendar.YEAR);
   int to_month = to_date.get(Calendar.MONTH)+1;
   int to_day = to_date.get(Calendar.DAY_OF_MONTH);
   DebugLogger.debug("to_year "+to_year+" to month "+to_month+" to day "+to_day);


   from_date.set(from_year, from_month, from_day);//set begin_of_goal_date
   to_date.set(to_year, to_month, to_day);//set now_date

   if(unit==0){
       //TODO unit for days difference
       return 0;
   }else if(unit==1){
       //TODO unit for week difference
       long milliseconds1 = from_date.getTimeInMillis();
       long milliseconds2 = to_date.getTimeInMillis();
       long diff = milliseconds2 - milliseconds1;
       long diffWeeks = diff / (7*24 * 60 * 60 * 1000);
       int weeks = (int) diffWeeks;
       DebugLogger.debug("Difference in weeks "+weeks);
       return weeks;
   }else{
       //TODO unit for years difference
       return 0;
   }

}

The above code is not working correctly, as it does not take date from and to as calendar object but instead gets a from_date and to_date equal today! What is wrong with my code?

UPDATE

this is the data i pass in my function

    String begin_of_goal_date="2016-01-20";//when we changed the goal
    String now_date="2016-04-18";//now
    int weeks = datesDifference(begin_of_goal_date,now_date,1);

Upvotes: 0

Views: 626

Answers (3)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 78965

java.time

The legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

Solution using the modern API:

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getDuration("2020-05-05", "2021-05-07", ChronoUnit.YEARS));
        System.out.println(getDuration("2020-05-05", "2021-05-07", ChronoUnit.MONTHS));
        System.out.println(getDuration("2020-05-05", "2021-05-07", ChronoUnit.DAYS));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.YEARS));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.MONTHS));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.DAYS));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.HOURS));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.MINUTES));
        System.out.println(getDuration("2020-05-05 10:20:30", "2021-05-07 5:10:15", ChronoUnit.SECONDS));
        System.out.println(getDuration("5:10:15", "10:20:30", ChronoUnit.HOURS));
        System.out.println(getDuration("5:10:15", "10:20:30", ChronoUnit.MINUTES));
        System.out.println(getDuration("5:10:15", "10:20:30", ChronoUnit.SECONDS));
    }

    public static long getDuration(String from, String to, ChronoUnit unit) {
        ZonedDateTime zdt = LocalDate.now().atStartOfDay(ZoneId.systemDefault());
        
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .appendPattern("[u-M-d][ ][H[:m[:s]]]")
                                .parseDefaulting(ChronoField.YEAR, zdt.getYear())
                                .parseDefaulting(ChronoField.MONTH_OF_YEAR, zdt.getMonthValue())
                                .parseDefaulting(ChronoField.DAY_OF_MONTH, zdt.getDayOfMonth())
                                .parseDefaulting(ChronoField.HOUR_OF_DAY, zdt.getHour())
                                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, zdt.getMinute())
                                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, zdt.getSecond()) 
                                .parseDefaulting(ChronoField.NANO_OF_SECOND, zdt.getNano()) 
                                .toFormatter(Locale.ENGLISH)
                                .withZone(ZoneId.systemDefault());
        
        return unit.between(ZonedDateTime.parse(from, dtf), ZonedDateTime.parse(to, dtf));
    }
}

Output:

1
12
367
1
12
366
8802
528169
31690185
5
310
18615

Note that DateTimeFormatter allows specifying optional patterns using square brackets. Alternatively, it can be done with the help of DateTimeFormatterBuilder#optionalStart and DateTimeFormatterBuilder#optionalEnd.

Learn more about the the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Upvotes: 1

Bajirao Shinde
Bajirao Shinde

Reputation: 1354

Simply use Joda Time

Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

http://joda-time.sourceforge.net/faq.html#datediff

Upvotes: 0

Jordi Castilla
Jordi Castilla

Reputation: 26961

If data example is in this format 2016-01-20

Change SimpleDateFormat format from yyyy-MMM-dd to yyyy-MM-dd:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

With this call:

datesDifference("2016-01-01", "2016-02-01", 1);

OUTPUT

From date = 2016-01-01 to date = 2016-02-01
from_year 2016 from month 1 from day 1
to_year 2016 to month 2 to day 1
Difference in weeks 4

With your example:

String begin_of_goal_date="2016-01-20";//when we changed the goal
String now_date="2016-04-18";//now
int weeks = datesDifference(begin_of_goal_date,now_date,1);

OUTPUT:

From date = 2016-01-20 to date = 2016-04-18
from_year 2016 from month 1 from day 20
to_year 2016 to month 4 to day 18
Difference in weeks 12

Upvotes: 2

Related Questions