I have a method which takes two String parameters. the two strings are Time values in 24 hour format. The Times are picked using a TimePicker from UI.
The goal of the method is to get the duration between the StartTime and EndTime in Minutes.
public static String getTimeDuration(String StartTime24, String EndTime24)
{
String duration = "";
try
{
SimpleDateFormat parseFormat = new SimpleDateFormat("HH:mm");
Date startTime = parseFormat.parse(StartTime24);
Date endTime = parseFormat.parse(EndTime24);
long mills = endTime.getTime() - startTime.getTime();
long minutes = mills/(1000 * 60);
duration = "(" + minutes + " Minutes)";
}
catch(ParseException ex)
{
// exception handling here
}
return duration;
}
The method works fine if both the times are within a Single Date. For example:
StartTime = 22:15
EndTime = 23:51
Output = (96 Minutes)
But my problem is, the method returns negative if the end time is after 12'o clock at night. For example,
StartTime = 23:51
EndTime = 0:55
Output = (-1376 Minutes)
What I want: (64 Minutes)
How can get the duration correct ?
As there is no date used, you have to check first if your endTime is less than your startTime. If yes, then your endTime is on the next day and you have to add 1 day/86 400 000 milliseconds. Then you will have your desired result.
Just add this condition:
if(endTime.getTime() < startTime.getTime()){
long mills = ((endTime.getTime() + 86400000) - startTime.getTime()); 1 day = 86 400 000 mill
}
Hope this helps
You're only parsing the minutes and hours. There's no day on there. So that puts both times on the same day (the first day of the epoch, Jan 1 1970 to be exact). So the answer is correct. If you want it to treat the end time as the next day if its earlier than the start time, then add 1 day to the result (1440 minutes) if the result is less than 0.
I am using a Date and Time Dialog to get a Date and Time for an Event Specifed by the User. That data is the Converted by doing the following:
int yearE = Integer.valueOf(evntDate.split("/")[2]);
int monthE = Integer.valueOf(evntDate.split("/")[1]);
int dayE = Integer.valueOf(evntDate.split("/")[0]);
int hour = Integer.valueOf(evntTm.split(":")[0]);
int min = Integer.valueOf(evntTm.split(":")[1]);
With the Values of:
eventDate = "3/5/2015";
eventTime = "13:2";
I then get that data and COnvert it into Milliseconds and Store that in the Database:
newCalendar.set(yearE, monthE, dayE,hour, min, 0);
startTime = newCalendar.getTimeInMillis();
...
When I load the Info from the Database, I try to calculate the amount of time left until the Specified date. So I do the following:
Long timeL = Long.valueOf(time);
Calendar eventDay = Calendar.getInstance();
eventDay.setTimeInMillis(timeL);
Calendar today = Calendar.getInstance();
long diff = eventDay.getTimeInMillis() - today.getTimeInMillis();
// CONVERT:
int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(diff);
int minutes = (int) TimeUnit.MILLISECONDS.toMinutes(diff);
int hours = (int) TimeUnit.MILLISECONDS.toHours(diff);
int days = (int) TimeUnit.MILLISECONDS.toDays(diff);
...
When I log the above data, the days are usually around 30-32 and the rest of the data is incorrect as well. What am I doing wrong? Or what are some alternatives?
Consider using the Joda time library instead of Calendar, it's much easier to work with.
As you're on android, I'll assume that you're using gradle, so go ahead and drop this in your dependencies
compile 'joda-time:joda-time:2.3'
I've created a small psvm to demo how you can use it
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.PeriodFormat;
import static java.lang.String.format;
public class DateTimeDemo {
public static void main(String[] args) {
// Your date/time values, I'll assume you missed a digit off the time ;)
String eventDate = "3/5/2015";
String eventTime = "13:20";
// convert these to a DateTime object
DateTime targetDateTime = DateTime.parse(format("%s %s", eventDate, eventTime), DateTimeFormat.forPattern("dd/MM/yyyy HH:mm"));
// print out the millis, or in your case, save it to DB
System.out.println("targetDateTime in millis is " + targetDateTime.getMillis());
// grab a timestamp
DateTime now = DateTime.now();
// print it out, just for demo
System.out.println("millis for now is " + now.getMillis());
// create a period object between the two
Period period = new Period(now, targetDateTime);
// print out each part
System.out.println("seconds " + period.getSeconds());
System.out.println("hours " + period.getHours());
System.out.println("months " + period.getMonths());
// convert the period to a printable String
String prettyPeriod = PeriodFormat.getDefault().print(period);
// write it out!
System.out.println(prettyPeriod);
}
}
Output is
targetDateTime in millis is 1430623200000
millis for now is 1425527593584
seconds 46
hours 22
months 1
1 month, 3 weeks, 6 days, 22 hours, 26 minutes, 46 seconds and 416 milliseconds
You can use Joda for that.
long dbTime = 1425525415837L;
Period period = new Period( dbTime, System.currentTimeMillis() );
String formatted = PeriodFormat.getDefault().print(period);
System.out.println( formatted );
If you want more control of the format use PeriodFormatter.
If you want to get the seconds, minutes, hours, etc. and not just print them, you can use the various available methods. For example:
period.getSeconds();
period.getHours();
period.getMonths();
More formatting options are described in this question.
Are you expecting to see something similar:
seconds = 36 (always less than 60)
minutes = 12 (always less that 60)
hours = 17 (always less than 24)
days = 45 (always less that 31 if # of months is used, else < 366 if # of years is used)
...
...
from:
// CONVERT:
int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(diff);
int minutes = (int) TimeUnit.MILLISECONDS.toMinutes(diff);
int hours = (int) TimeUnit.MILLISECONDS.toHours(diff);
int days = (int) TimeUnit.MILLISECONDS.toDays(diff);
Its a logical error then. TimeUnit.MILLISECONDS.toXXXX(long) converts the whole time-difference into the specified units. This is of no value to you.
As an example, say you set the event's date to 32 days from now - and time to 13:15.
Millisecond difference =
2764800000 (32 days in millis)
+ 46800000 (13 hours in millis)
+ 900000 (15 minutes in millis)
= 2812500000
Using this time-difference, the following log:
int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(diff);
int minutes = (int) TimeUnit.MILLISECONDS.toMinutes(diff);
int hours = (int) TimeUnit.MILLISECONDS.toHours(diff);
int days = (int) TimeUnit.MILLISECONDS.toDays(diff);
produces:
Seconds left: 2812500
Minutes left: 46875
Hours left: 781
Days left: 32
These figures are not off. A quick check would be: time difference in millis was: 2812500000 => in seconds would be diff/1000 = 2812500 => in minutes would be => diff/1000/60 = 46875 and so on.
Relative time:
To get relative time such as 32 days, 13 hours and 15 minutes left, you will have to do the heavy-lifting yourself. As an example:
// I will use the actual values instead of defined
// variables to make this easier to follow
long timeDiff = 2812500000L;
// Simple division // we don't care about the remainder
// Result: 32
int days = 2812500000 / DateUtils.DAY_IN_MILLIS;
// This is what's left over after we take the days out.
// We'll use this to get the number of hours.
// Result: 47700000
long remainderFromDays = 2812500000 % DateUtils.DAY_IN_MILLIS;
// Simple division // we don't care about the remainder
// Result: 13
int hours = 47700000 / DateUtils.HOUR_IN_MILLIS;
// This is what's left over after we take the hours out.
// We'll use this to get the number of minutes.
// Result: 900000
long remainderFromHours = 47700000 % DateUtils.HOUR_IN_MILLIS;
// Result: 15
int minutes = 900000 / DateUtils.MINUTE_IN_MILLIS;
// Result: 0
long remainderFromMinutes = 900000 % DateUtils.MINUTE_IN_MILLIS;
// Result: 0
int seconds = 0 / 1000; // 1000 ms = 1 sec
Log.i("Time-Difference", "Event in: " + String.format("Event in %d days, %d hours, %d minutes and %d seconds", days, hours, minutes, seconds));
Output:
Event in: 32 days, 13 hours, 15 minutes and 0 seconds
This is the very reason everyone here is suggesting Joda Time. The computation above is just off the top of my head. I cannot guarantee its correctness. If you also need relative month difference (such as 3 months, 2 days ....), a lot of work will be required. There isn't a DateUtils.MONTH_IN_MILLIS constant - varying number of days - 28, 29, 30, 31.
On the other hand, Joda Time is a tried & tested product. But, if all you need is one kind of computation, used scarcely (if ever), I'd say spend some time and come up with your own implementation rather than under-employ Joda Time.
Your code looks fine to me for what you are doing. Using org.joda.time as others have suggested is a best-practice, but it won't fix the problem. Instead you need to do two things:
Verify the Month that the user entered is in range (they may have entered the date in MM/DD/YYYY format). Month values greater than 12 won't throw an exception and your diff will be way off.
The line where you construct your date, subtract 1 from the month since months should be from 0 to 11, like:
newCalendar.set(yearE, monthE-1, dayE,hour, min, 0);
I have developed an application where the user receives the message from other application user. I want to just show the time like Facebook, eg. 1sec ago or 3Hrs ago. Something in this fashion. I tried a code from one of our Fellow S.O expert but that code seems to misbehave.
Here's the code which i used in my app.
static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
static int[] steps = { 1, 60, 3600, 3600 * 24 };
static String[] names = { "sec", "mins", "hrs", "days" };
public static String formatDelay(String date) {
try {
Date d = sdf.parse(date);
Long stamp = d.getTime();
Calendar c = Calendar.getInstance();
Long now = System.currentTimeMillis() / 1000;
Format format = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
String time = format.format(now);
Long dif = now - stamp;
dif = dif / 1000;
if (stamp > now)
return "";
for (int i = 0; i < steps.length; i++) {
if (dif < steps[i]) {
String output = Long.toString(dif / steps[i - 1]) + " "
+ names[i - 1];
return output;
}
}
return Long.toString(dif / steps[3]) + " " + names[3];
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
When I used this code and sent a message from my application , it should show me sent 1sec ago, but in my case it shows me wrong time delay. For eg. I sent the message at 6pm then when I check my application sent item at 6:15pm its should show me 15 mins ago. But it shows me 12 hrs. When i debugged code, got to know that now time show date as 1970 00:00:00, this is because Long now = System.currentTimeMillis() / 1000; when i remove that /1000 it shows me correct date and time. I am clue less why this is happening please help.
Use
android.text.format.DateUtils.getRelativeTimeSpanString (long time, long now, long minResolution, int flags)
this will return time span in String format
For eg. if you pass a long value corresponding to 42 minutes ago in time and flags as DateUtils.FORMAT_ABBREV_RELATIVE the method will return 42 minutes ago
Official documentation DateUtils.getRelativeTimeSpanString
When you divide System.currentTimeMillis() by 1000 you are converting its value to seconds.
You're then using that value to create a date which is interpreting the seconds value as the milliseconds since Thu Jan 01 1970, hence the date difference.
I would recommend using Joda-Time API. See this answer for reference.
I have TimePicker in my Registration class to ask the user for their free time each day but it display the time in 24 hour format and I don't know how to view the time in a 12 hour format
I'm getting the value of TimePicker using
int hour = timepicker.getCurrentHour();
int min = timepicker.getCurrentMinute();
String time = hour + ":" + min;
and I also want to get the value of AM/PM
int hour = timepicker.getCurrentHour();
int min = timepicker.getCurrentMinute();
String state = "am";
if(hour > 12){
hour -=12;
state = "pm";
}
String time = hour + ":" + min + ":" + state;
PS: if you want the view itself show the time in 12-hours format you can add timepicker.setIs24HourView(false);
i am using the code below:
endTimeEntryCal2.before(addTimeEntryCale)
to check if user set time is before current time but i also want it to be before or equal to is there anyway of doing this here eg something like before=();
This does the trick:
endTimeEntryCal2.compareTo(addTimeEntryCale) <= 0
int compareTo(Calendar anotherCalendar)
Compares the times of the two Calendar, which represent the
milliseconds from the January 1, 1970 00:00:00.000 GMT (Gregorian).
Parameters anotherCalendar another calendar that this one is compared with
Returns:
0 if the times of the two Calendars are equal,
-1 if the time of this Calendar is before the other one
1 if the time of this Calendar is after the other one.
long mills = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
int x = (mills <= currentTime)?0:1;
if(x == 1)
{
// Time Available
}else
{
//Time passed
}