-1

I'm working in this code for about 12 hors now, and still can't make it work. DISCLAIMER: I'm working with Date -not Calendar, nor Instant- because I'm codding for API 15 (my smartphone).

This is what I want to do:

I have several EditView(s) where user can write. Example

EditText StartDateEditText = (EditText) findViewById(R.id.getStartDate_editText);
EditText EndDateEditText = (EditText) findViewById(R.id.getEndDate_editText);
EditText StartHourEditText = (EditText) findViewById(R.id.getStartHour_editText);

I need to recover that info (String) and convert it into date/time. Example:

SimpleDateFormat StartFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
        String StartAssembled = StartDateToString + " " + StartTimeToString;
        Date StartMoment = null;
        try {
            StartMoment = StartFormat.parse(StartAssembled);
        } catch (ParseException e) {
            e.printStackTrace();
        }

Lastly, I need to find time elapsed and show it:

long difference = EndMoment.getTime() - StartMoment.getTime();
long differenceSeconds = difference / 1000;
long differenceMinutes = differenceSeconds % 60;
long differenceHours = differenceSeconds % (60 * 60);
String differenceToString = "Hours: " + String.valueOf(differenceHours) +
        " Minutes: " + String.valueOf(differenceMinutes) +
        " Seconds: " + String.valueOf(differenceSeconds);
Log.v("MainActivity:", differenceToString);

Now, user inputs_ Start 29/09/2017 12:01 End 29/09/2017 16:31

And I get...

09-29 15:23:54.213 7798-7798/com.example.android.timeismoney V/MainActivity: Hours: 0 Minutes: 0 Seconds: 0

By the way: same verbose comes out from StartJobDate - EndJobDate

But it should log: Hours: 4 Minutes: 30 Seconds: 0

I'm new to java and newer to time managing. Would apreciate any help. Any advices or hints to do this better?


Following, I copy and comment my code:

Imports and such:

package com.example.android.timeismoney;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

Method named "cosa" (english "thing") because is my playground. Called from onClick in a button in xml.

public void cosa(View view) {

From here I focus EditText(s)

    EditText StartDateEditText = (EditText) findViewById(R.id.getStartDate_editText);
    EditText EndDateEditText = (EditText) findViewById(R.id.getEndDate_editText);
    EditText StartHourEditText = (EditText) findViewById(R.id.getStartHour_editText);
    EditText StartMinuteEditText = (EditText) findViewById(R.id.getStartMinute_editText);
    EditText EndHourEditText = (EditText) findViewById(R.id.getEndHour_editText);
    EditText EndMinuteEditText = (EditText) findViewById(R.id.getEndMinute_editText);

Now I recover text

String StartDateToString = StartDateEditText.getText().toString();
String StartTimeToString = StartHourEditText.getText().toString() +
               ":" + StartHourEditText.getText().toString();
String EndDateToString = EndDateEditText.getText().toString();
String EndTimeToString = EndHourEditText.getText().toString() +
               ":" + EndHourEditText.getText().toString();

Here I set Date vars and fill them with data from EditText(s)

SimpleDateFormat StartFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
String StartAssembled = StartDateToString + " " + StartTimeToString;
Date StartMoment = null;
try {
    StartMoment = StartFormat.parse(StartAssembled);
} catch (ParseException e) {
    e.printStackTrace();
}

SimpleDateFormat EndFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm");
String EndAssembled = EndDateToString + " " + EndTimeToString;
Date EndMoment = null;
try {
    EndMoment = EndFormat.parse(EndAssembled);
} catch (ParseException e) {
    e.printStackTrace();
}

Now I operate and get milliseconds. I convert them. Then, show them.

    long difference = StartMoment.getTime() - EndMoment.getTime();
    long differenceSeconds = difference / 1000;
    long differenceMinutes = difference / (60 * 1000);
    long differenceHours = difference / (1000 * 60 * 60);
    String differenceToString = "Hours: " + String.valueOf(differenceHours) +
            " Minutes: " + String.valueOf(differenceMinutes) +
            " Seconds: " + String.valueOf(differenceSeconds);
    Log.v("MainActivity:cosa()", differenceToString);


}

Here my entire MainActivity.java: https://github.com/Hinuden/ShowAndTell/commits/master/TimeIsMoney29-09-2017-MainActivity.java

Here my entire activity_main.xml: https://github.com/Hinuden/ShowAndTell/blob/master/TimeIsMoney-29-09-2017-activity_main.xml

Thanks for help.

Josue Fas
  • 39
  • 7
  • 1
    Your code example is too log. Can you edit it to be small as possible yet a complete example of your problem? – jwils Sep 29 '17 at 15:37
  • 1
    When you create the differenceToString you don't need to call String.valueOf. You can just concatenate like this: String differenceToString = "Hours: " + differenceHours + " Minutes: " + differenceMinutes + " Seconds: " + differenceSeconds; – jwils Sep 29 '17 at 15:48
  • 1
    For debugging purposes you should print out "difference", as well as "StartMoment.getTime()" and "EndMoment.getTime()". – jwils Sep 29 '17 at 15:51
  • What data are you putting into those text fields? What result are you expecting to get printed out? If you aren't putting anything into the fields then maybe get all 0's is what you should be getting. – jwils Sep 29 '17 at 15:52
  • 1
    Have you checked the values of `StartAssembled` and `EndAssembled` when getting 0 as output? I've just tested with `10/10/2017 10:00` and `10/10/2017 15:00` and got `Hours: 5 Minutes: 300 Seconds: 18000` –  Sep 29 '17 at 16:15
  • Maybe I'm missing something, but just tested with your data: `SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy HH:mm"); Date start = f.parse("29/09/2017 12:01"); Date end = f.parse("29/09/2017 16:31"); long difference = end.getTime() - start.getTime(); etc` and the output is `Hours: 4 Minutes: 270 Seconds: 16200`. Are you sure you're getting all zeroes? –  Sep 29 '17 at 16:46

2 Answers2

1

I don't really know what kind of black magic is happening here. Since most of you reported code worked, I couldn't get nothing but zero(s).

BUT Gandalf came to help in the person of JIWILS who wrote:

When you create the differenceToString you don't need to call String.valueOf. You can just concatenate like this: String differenceToString = "Hours: " + differenceHours + " Minutes: " + differenceMinutes + " Seconds: " + differenceSeconds; – jwils 1 hour ago

I changed this:

String differenceToString = "Hours: " + String.valueOf(differenceHours) +
            " Minutes: " + String.valueOf(differenceMinutes) +
            " Seconds: " + String.valueOf(differenceSeconds);

To this:

String differenceToString = "Hours: " + differenceHours +
                " Minutes: " + differenceMinutes +
                " Seconds: " + differenceSeconds;

And works perfectly. Where problem was? Absolutely no idea. But it works.

Additionally I rewrote algorithm like this:

long difference = EndMoment.getTime() - StartMoment.getTime();
        long differenceHours = difference / (1000 * 60 * 60);
        long differenceMinutes = (difference % (1000 * 60 * 60)) / (1000 * 60);
        long differenceSeconds = ((difference % (1000 * 60 * 60)) % (1000 * 60)) / 1000;

Now difference between Start and End is shown pefectly.

Josue Fas
  • 39
  • 7
1

I've tested your code and didn't get zeroes in the output:

SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy HH:mm");
Date start = f.parse("29/09/2017 12:01");
Date end = f.parse("29/09/2017 16:31");
long difference = (end.getTime() - start.getTime());
// ... same code as yours

Instead, I've got this output:

Hours: 4 Minutes: 270 Seconds: 16200

I didn't get the zeroes, but anyway, there's a problem in the way you're calculating the values. You're getting the equivalent to the total number of seconds, instead of breaking it into each time unit. You should do this instead:

long differenceSeconds = (end.getTime() - start.getTime()) / 1000;
long differenceHours = differenceSeconds / 3600;
// discount the total hours
differenceSeconds -= (differenceHours * 3600);
long differenceMinutes = differenceSeconds / 60;
// discount the total seconds
differenceSeconds -= (differenceMinutes * 60);

Now the value of differenceToString will be:

Hours: 4 Minutes: 30 Seconds: 0


Notes:

  • As the input has only hours and minutes, you can discard the seconds (they'll always be zero), so you can also do the calculations directly from the minutes.
  • You don't need to use String.valueOf. As you're concatenating the number with a String, just use its value directly
  • As you noticed from above, I used the same SimpleDateFormat instance, because the start and end dates have the same format.

So your calculation would be like this:

long differenceMinutes = (end.getTime() - start.getTime()) / 1000 / 60;
long differenceHours = differenceMinutes / 60;
// discount the number of hours
differenceMinutes -= (differenceHours * 60);
// seconds is always zero, because I'm not considering in the input
String differenceToString = "Hours: " + differenceHours + " Minutes: " + differenceMinutes + " Seconds: 0";

Joda-Time

I'd normally suggest ThreeTen Backport, but it works only with JDK 6 and 7, so for JDK 5 you could use Joda-Time, a great API to deal with date/time stuff.

First you create a org.joda.time.format.DateTimeFormatter, using a org.joda.time.format.DateTimeFormat and the desired pattern. Then I parse the inputs to a org.joda.time.DateTime and use a org.joda.time.Period to calculate the difference between the dates.

Then I can use the Period directly or use a org.joda.time.format.PeriodFormatter to format the difference:

// parse dates
DateTimeFormatter f = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm");
DateTime start = f.parseDateTime("29/09/2017 12:01");
DateTime end = f.parseDateTime("29/09/2017 16:31");
// calculate difference
Period diff = new Period(start, end);

String differenceToString = "Hours: " + diff.getHours() + " Minutes: " + diff.getMinutes() + " Seconds: " + diff.getSeconds();
System.out.println(differenceToString);

The output will be:

Hours: 4 Minutes: 30 Seconds: 0

I can also use a PeriodFormatter:

PeriodFormatter pf = new PeriodFormatterBuilder()
    // hours
    .appendPrefix("Hours: ").appendHours()
    // optional space (if there are more fields)
    .appendSeparatorIfFieldsBefore(" ")
    // minutes
    .appendPrefix("Minutes: ").appendMinutes()
    // optional space (if there are more fields)
    .appendSeparatorIfFieldsBefore(" ")
    // seconds
    .appendPrefix("Seconds: ").appendSeconds()
    // create formatter
    .toFormatter();
System.out.println(pf.print(diff));

The difference is that it omits the seconds if the value is zero:

Hours: 4 Minutes: 30

  • 1
    I have code running now. But I'm putting your answer in favs and will study Joda-Time topic for refine process in future. Thank you! – Josue Fas Sep 29 '17 at 17:25
  • 1
    @JosueFas You're welcome, glad to help! In the future, if you change to JDK 6 or 7, prefer to use [ThreeTen Backport](http://www.threeten.org/threetenbp), a backport for Java 8's [new java.time API](https://docs.oracle.com/javase/tutorial/datetime). That's because Joda-Time is in maintainance mode and is being replaced by the new APIs. Even in [joda's website](http://www.joda.org/joda-time) it says: **"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310)."** –  Sep 29 '17 at 17:29
  • @JosueFas To use ThreeTen Backport in Android, you'll also need the [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) (more on how to use it [here](https://stackoverflow.com/a/38922755/7605325)). Anyway, I just suggested Joda-Time because it's still the best alternative for JDK <= 5. –  Sep 29 '17 at 17:29