Search code examples
javadatetimedatepickerdate-differenceandroid-date

Calculate the difference between Current Date and Past Date


Experts, trying to show the difference between two dates in Android Studio. Have got following conditions.

Below Condition number one is working fine. 1. Difference between current date vs future date

Condition 2 has issue were it shows the value but its not showing negative symbol to understand its already passed.

  1. Difference between current date and past date.

Main activity.

package com.bar.example.myapplication;

import android.app.DialogFragment;
//import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

  private EditText editTextDate1, editTextDate2, num1, num2;
  private TextView txtResult, tv, textDivNumber, textAVG, txtZaMisiac;
  private Button button;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editTextDate1 = (EditText) findViewById(R.id.editTextDate1);
    editTextDate2 = (EditText) findViewById(R.id.editTextDate2);
    num1 = (EditText) findViewById(R.id.num1);
    num2 = (EditText) findViewById(R.id.num2);
    button = (Button) findViewById(R.id.button);
    txtResult = (TextView) findViewById(R.id.txtResult);
    textDivNumber = (TextView) findViewById(R.id.textDivNumber);
    textAVG = (TextView) findViewById(R.id.textAVG);
    txtZaMisiac = (TextView) findViewById(R.id.txtZaMisiac);
    tv = (TextView) findViewById(R.id.tv);
    tv.setText("Current date " + (DateFormat.format("dd.MM.yyyy", new java.util.Date()).toString()));
    editTextDate1.setText(DateFormat.format("dd.MM.yyyy", new java.util.Date()).toString());

  }

  public void diff(View view) {
    SimpleDateFormat myFormat = new SimpleDateFormat("dd.MM.yyyy");
    String inputString1 = editTextDate1.getText().toString();
    String inputString2 = editTextDate2.getText().toString();
    String number11 = num1.getText().toString();
    String number12 = num2.getText().toString();

    String[] isbnParts = inputString1.split("\\.");
    if (Integer.parseInt(isbnParts[0]) > 31) {
      Toast.makeText(this, "It looks like you've typed too many days in a month", Toast.LENGTH_SHORT).show();
    }
    if (Integer.parseInt(isbnParts[1]) > 12) {
      Toast.makeText(this, "Gm ... introduced a non-existent month)", Toast.LENGTH_SHORT).show();
    }

    String[] isbnParts1 = inputString2.split("\\.");
    if (Integer.parseInt(isbnParts1[0]) > 31) {
      Toast.makeText(this, "Hey ... too many days in a month", Toast.LENGTH_SHORT).show();
    }
    if (Integer.parseInt(isbnParts1[1]) > 12) {
      Toast.makeText(this, "Hmm ... you entered a non-existent month)", Toast.LENGTH_SHORT).show();
    }

    if (inputString1.matches("") || inputString2.matches("")) {
      Toast.makeText(this, "No dates entered", Toast.LENGTH_SHORT).show();
    } else {

      try {
        Date date1 = myFormat.parse(inputString1);
        Date date2 = myFormat.parse(inputString2);
        long diffDate = Math.abs(date2.getTime() - date1.getTime());
        txtResult.setText("" + TimeUnit.DAYS.convert(diffDate, TimeUnit.MILLISECONDS));

      } catch (ParseException e) {
        e.printStackTrace();
      }
      if (number11.matches("") || number12.matches("")) {
        Toast.makeText(this, "No numbers entered for calculation", Toast.LENGTH_SHORT).show();
      } else {

        String pattern = "##0.00";
        String pattern1 = "##0";
        DecimalFormat decimalFormat = new DecimalFormat(pattern);
        DecimalFormat decimalFormat1 = new DecimalFormat(pattern1);

        float number1 = Integer.parseInt(number11);
        float number2 = Integer.parseInt(number12);
        float diffDateInt = Integer.parseInt(txtResult.getText().toString());
        float diffnumb = Math.abs(number1 - number2);
        String format3 = decimalFormat1.format(diffnumb);
        textDivNumber.setText(String.valueOf(format3));
        String format = decimalFormat.format((diffnumb / diffDateInt) * 30.00);
        txtZaMisiac.setText(String.valueOf(format));
        String format1 = decimalFormat.format(diffnumb / diffDateInt);
        textAVG.setText(String.valueOf(format1));
      }
    }
  }

  public void setDate1(View view) {
    DialogFragment newFragment = new DatePickerFragment();
    newFragment.show(getFragmentManager(), "Date Picker");
  }
  public void setDate2(View view) {
    DialogFragment newFragment = new DatePickerFragment2();
    newFragment.show(getFragmentManager(), "Date Picker");
  }
}

DatePickerFragment.java

package com.bar.example.myapplication;

import android.app.DatePickerDialog;
import android.app.DialogFragment;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.DatePicker;
import android.app.Dialog;
import java.util.Calendar;

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {

    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);
    return new DatePickerDialog(getActivity(), this, year, month, day);
  }
  public void onDateSet(DatePicker view, int year, int month, int day) {
    EditText editTextDate1 = (EditText) getActivity().findViewById(R.id.editTextDate1);
    String stringOfDate = day + "." + (month + 1) + "." + year;
    editTextDate1.setText(stringOfDate);
  }
}

DatePickerFragment2.java

package com.bar.example.myapplication;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.os.Bundle;
import android.widget.DatePicker;
import android.widget.EditText;


import java.util.Calendar;

public class DatePickerFragment2 extends DialogFragment implements DatePickerDialog.OnDateSetListener {

  @Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {

    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);
    return new DatePickerDialog(getActivity(), this, year, month, day);
  }

  public void onDateSet(DatePicker view, int year, int month, int day) {
    EditText editTextDate2 = (EditText) getActivity().findViewById(R.id.editTextDate2);
    String stringOfDate = day + "." + (month + 1) + "." + year;
    editTextDate2.setText(stringOfDate);
  }
}

layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:background="#B3E5FC"
    tools:context=".MainActivity"
    >
    <!--This example works only date picker mode = spinner mode only-->
    <!--DatePicker with spinner and without Calendar-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="set date 1"
        android:id="@+id/btnDate1" android:layout_alignParentTop="true" android:layout_alignParentLeft="true"
        android:layout_marginTop="42dp" android:onClick="setDate1"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="set date 2"
        android:id="@+id/btnDate2" android:layout_alignTop="@+id/btnDate1" android:layout_alignParentRight="true"
        android:onClick="setDate2"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="calculate"
        android:id="@+id/button"
        android:onClick="diff" android:layout_centerVertical="true" android:layout_centerHorizontal="true"
        android:textColor="#f21124"/>
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editTextDate1" android:layout_below="@+id/btnDate1" android:layout_alignParentLeft="true"
        android:layout_alignRight="@+id/btnDate1"
        android:inputType="date" android:textColor="#9e0e1f" android:textSize="15dp"/>
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editTextDate2" android:layout_below="@+id/btnDate2"
        android:layout_alignRight="@+id/btnDate2" android:layout_alignLeft="@+id/btnDate2"
        android:inputType="date" android:textColor="#e11515" android:textSize="15dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/txtResult"
        android:text="............"
        android:textSize="14dp" android:layout_below="@+id/button" android:layout_alignLeft="@+id/num2"
        android:layout_alignStart="@+id/num2" android:textColor="#5c2e2e"/>
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:id="@+id/num1" android:layout_below="@+id/editTextDate1" android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_toStartOf="@+id/button" android:layout_alignRight="@+id/editTextDate1"
        android:layout_alignEnd="@+id/editTextDate1" android:textColor="#590e9b" android:textSize="15dp"/>
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:ems="10"
        android:id="@+id/num2" android:layout_below="@+id/editTextDate2" android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" android:layout_alignLeft="@+id/editTextDate2"
        android:layout_alignStart="@+id/editTextDate2" android:textColor="#3818ad" android:textSize="15dp"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/txtResult"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:text="Between dates"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#060606"
        android:textSize="14dp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textView"
        android:text="The difference between the numbers"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#070707"
        android:textSize="14dp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="............"
        android:id="@+id/textDivNumber"
        android:layout_below="@+id/txtResult" android:layout_alignLeft="@+id/txtResult"
        android:layout_alignStart="@+id/txtResult" android:textColor="#782f2f" android:textSize="14dp"/>

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textView2"
        android:text="Average value"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#0a0a0a"
        android:textSize="14dp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="............"
        android:id="@+id/textAVG"
        android:layout_below="@+id/textDivNumber" android:layout_alignLeft="@+id/textDivNumber"
        android:layout_alignStart="@+id/textDivNumber" android:textColor="#7e3333" android:textSize="14dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Small Text"
        android:id="@+id/tv"
        android:layout_alignParentTop="true" android:layout_centerHorizontal="true"/>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/textDivNumber"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:text="days"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView3"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignStart="@+id/textView3"
        android:layout_below="@+id/textDivNumber"
        android:text="in a day"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textSize="10dp" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignTop="@+id/txtZaMisiac"
        android:text="Per month"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#171414"
        android:textSize="14dp" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="............"
        android:id="@+id/txtZaMisiac"
        android:layout_below="@+id/textView5" android:layout_alignLeft="@+id/textAVG"
        android:layout_alignStart="@+id/textAVG" android:textSize="14dp" android:textColor="#052df7"/>
</RelativeLayout>

Condition number one which is working fine(Current date vs future date). below screenshot. enter image description here

Condition number two(Current date vs past date) which shows value instead of negative value -29. enter image description here

new diff code

public void diff(View view) {

  //  SimpleDateFormat myFormat = new SimpleDateFormat("dd.MM.yyyy");
  // String inputString1 = ok.getText().toString();
  //  String inputString2 = ok1.getText().toString();
  CharSequence inputString1 = editTextDate1.getText();

  try {
    LocalDate date1 = LocalDate.parse(inputString1, dateFormatter);
    CharSequence inputString2 = editTextDate2.getText();
    try {
      LocalDate date2 = LocalDate.parse(inputString2, dateFormatter);
      long diffDate = ChronoUnit.DAYS.between(date1, date2);
      txtResult.setText(String.valueOf(diffDate));
    } catch (DateTimeParseException dtpe) {
      Toast.makeText(this, "Date2 is not a valid date: " + inputString2, Toast.LENGTH_SHORT).show();
    }
  } catch (DateTimeParseException dtpe) {
    Toast.makeText(this, "Date1 is not a valid date: " + inputString1, Toast.LENGTH_SHORT).show();
  }
  //   if (number11.matches("")||number12.matches("")){Toast.makeText(this, "No numbers entered for calculation", Toast.LENGTH_SHORT).show();}

}


Solution

  • java.time

    Let’s first declare a formatter. This may be a static field:

    private static DateTimeFormatter dateFormatter
            = DateTimeFormatter.ofPattern("d.M.uuuu");
    

    Then in your diff method in MainActivity you may do something like:

        CharSequence inputString1 = editTextDate1.getText();
        try {
            LocalDate date1 = LocalDate.parse(inputString1, dateFormatter);
            CharSequence inputString2 = editTextDate2.getText();
            try {
                LocalDate date2 = LocalDate.parse(inputString2, dateFormatter);
                long diffDate = ChronoUnit.DAYS.between(date1, date2);
                txtResult.setText(String.valueOf(diffDate));
            } catch (DateTimeParseException dtpe) {
                Toast.makeText(this, "Date2 is not a valid date: " + inputString2, Toast.LENGTH_SHORT).show();
            }
        } catch (DateTimeParseException dtpe) {
            Toast.makeText(this, "Date1 is not a valid date: " + inputString1, Toast.LENGTH_SHORT).show();
        }
    
    • If the dates are 5.5.2018 and 31.5.2018, it shows a difference of 26.
    • If the dates are 5.5.2018 and 1.5.2018, it shows a difference of -4.

    What went wrong in your code?

    I believe this line was the culprit:

            long diffDate = Math.abs(date2.getTime() - date1.getTime());
    

    Math.abs() takes the absolute value of the argument, that is, converts a negative number to a positive one. So no matter whether the date was in the past or in the future, you get a positive number here. After converting from milliseconds to days you still have a positive number, so it is displayed without a sign.

    That said, the date and time classes you were using, Calendar, Date and SimpleDateFormat, are long outdated and poorly designed. SimpleDateFormat in particular is notoriously troublesome. Consider avoiding them and using java.time, the modern Java date and time API, 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 new Android devices (from API level 26, I’m told) the new API comes built-in.
    • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310, where the modern API was first described).
    • On (older) Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. Make sure you import the date and time classes from package org.threeten.bp and subpackages.

    Links