This question already has answers here:
Calculate Difference between two times in Android
(7 answers)
Closed 2 years ago.
I have two hours, in the format (HH: mm) that I have passed to Date to subtract.
By subtracting them, I get the difference in milliseconds, and I convert them to hours dividing by 3600, and to minutes, first dividing by 60, and then doing the% operation.
If, for example, I put the starting time 20:00 and the final time 22:00, I get 0 hours and 2 minutes as a result.
Does anyone see the error?
This is my code:
hIni.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int hour = calendario.get(Calendar.HOUR_OF_DAY);
int minute = calendario.get(Calendar.MINUTE);
final TimePickerDialog.OnTimeSetListener time = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int hour, int minute) {
calendario.set(Calendar.HOUR_OF_DAY, hour);
calendario.set(Calendar.MINUTE, minute);
horaInicio = String.format("%02d:%02d", hour, minute);
hIni.setText(horaInicio);
if (!horaFin.equals(""))
{
if (testChar(hFin.toString()))
{
Date hI = ParseHora(horaInicio);
Date hF = ParseHora(horaFin);
//obtienes la diferencia de las fechas
long difference = Math.abs(hF.getTime() - hI.getTime());
//obtienes la diferencia en minutos ya que la diferencia anterior esta en milisegundos
difference= difference / (60 * 1000);
horasDur=difference/60;
minDur = difference%60;
dur.setText(horasDur +" horas "+minDur+" minutos");
}
}
}
};
new TimePickerDialog(NueAvaCuando.this,time, hour, minute, true).show();
}
});
hFin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int hour = calendario.get(Calendar.HOUR_OF_DAY);
int minute = calendario.get(Calendar.MINUTE);
final TimePickerDialog.OnTimeSetListener time = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int hour, int minute) {
calendario.set(Calendar.HOUR_OF_DAY, hour);
calendario.set(Calendar.MINUTE, minute);
horaFin = String.format("%02d:%02d", hour, minute);
hFin.setText(horaFin);
if (!horaInicio.equals(""))
{
if (testChar(hIni.toString()))
{
Date hI = ParseHora(horaInicio);
Date hF = ParseHora(horaFin);
//obtienes la diferencia de las fechas
long difference = Math.abs(hF.getTime() - hI.getTime());
//obtienes la diferencia en horas ya que la diferencia anterior esta en milisegundos
difference= difference / (60 * 60 * 1000);
horasDur=difference/60;
minDur = difference%60;
dur.setText(horasDur +"horas "+minDur+" minutos");
}
}
}
};
new TimePickerDialog(NueAvaCuando.this,time, hour, minute, true).show();
}
});
here the methods:
public static Date ParseHora(String fecha)
{
SimpleDateFormat formato = new SimpleDateFormat("HH:mm");
Date fechaDate = null;
try {
fechaDate = formato.parse(fecha);
}
catch (ParseException ex)
{
System.out.println(ex);
}
return fechaDate;
}
public boolean testChar(String cadena) {
if (!Character.isDigit(cadena.charAt(0)))
return true;
else
return false;
}
thank you very much
The problem is here, inside the onTimeSet method, defined inside the listener passed to hFin.setOnClickListener:
difference= difference / (60 * 60 * 1000);
Before this statement is executed, difference is in milliseconds. The code after this is expecting minutes. However, dividing by 1000 converts milliseconds to seconds, and therefore dividing by 60 * 1000 already gets you to minutes, so dividing by 60 * 60 * 1000 converts to hours, which is not what you want.
That part of the code should be:
difference = difference / (60 * 1000);
Related
I have a TimePicker with an interval of 30 minutes. When I open up a custom dialog with this picker it works well and it shows me 2 choices correctly (0, 30) in the minutes spinner. But, when I confirm and I come back to the activity it shows me a wrong result like: 10:01 instead 10:30. That's the method I use to set the interval
public static void setTimePickerInterval(TimePicker timePicker) {
try {
NumberPicker minutePicker = (NumberPicker) timePicker.findViewById(Resources.getSystem().getIdentifier("minute", "id", "android"));
minutePicker.setMinValue(0);
minutePicker.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
minutePicker.setDisplayedValues(displayedValues.toArray(new String[0]));
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
}
}
TIME_PICKER_INTERVAL is set as 30. And that's what i wrote in the activity inside the method that open a custom dialog with the picker
// Get time picker object.
TimePicker timePicker = customView.findViewById(R.id.timePickerExample);
Utils.setTimePickerInterval(timePicker);
timePicker.setIs24HourView(true);
timePicker.setHour(hour);
timePicker.setMinute(minute);
dpStartDate.init(year, month, day, new DatePicker.OnDateChangedListener() {
#Override
public void onDateChanged(DatePicker datePicker, int year, int month, int day) {
MainActivity.this.year = year;
MainActivity.this.month = month;
MainActivity.this.day = day;
}
});
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int hour, int minute) {
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour);
MainActivity.this.hour = hour;
MainActivity.this.minute = minute;
}
});
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour); shows what I'm setting. The hours are corrected, minutes not. It seems that instead shows "0, 30" it shows and select "0, 1". Any idea?
import java.text.SimpleDateFormat;
import java.util.Date;
public class Rate_Per_Hour {
public static void main(String[] args) {
String TimeStart = "09.30.00 am";
String TimeEnd= "10.10.00 am";
SimpleDateFormat format = new SimpleDateFormat("hh.mm.ss a");
int total=0;
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(TimeStart);
d2 = format.parse(TimeEnd);
long diff = d2.getTime() - d1.getTime();
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffMinutes = diff / (60 * 1000) % 60;
if (diffMinutes <= 30) {
total = 20;
}
else if (diffHours <=1){
total = 35;
}
System.out.println("Rs." +total);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I want output like this:
(Fixed rate per hour for this is Rs.35 )
For 30 min = Rs.20
For 40 min = Rs.25 and so on......
For 1 hour = Rs.35
For 1 hour 10 min = Rs.40
Please help me, figure out how I can do this.
Since the rate increases by 5 every 10 minutes, so just use a simple function to return the rate:
public double rate(int minutes)
{
return 20 + 5*((minutes - 30)/10);
}
Calculate the number of minutes and then pass it as an argument in that function to get the rate. Also, try to keep your code as short as possible but at the same time, simple.
if you need something more flexible rather than fixed rate you could implement an enum with predefined stops
you could define any rate you want for a given time.
for example if long running tasks shall gain higher rates (from your question it was not obvious to me if this rate shall be just the calculated value as in Manish Kundu's answer or if other values might get assigned.)
with this code you could assign higher rates for long running jobs (for example in computer games, jobs that are harder to achieve you return a higher rate or you lower the rate because the player took too much time...)
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class TimeMain {
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("hh.mm.ss[ ]a");
public enum Rate {
STOP0(0, 0, 0), // default
STOP1(0, 30, 20), // 30 mins -> Rs.20
STOP2(0, 40, 25), // 40 mins -> Rs.25
STOP3(1, 0, 35), // 1 hour -> Rs.35
STOP4(1, 10, 40); // 1 hour 10 minutes -> Rs.40
int minutes = 0;
int rate = 0;
/*
* hours is actually not needed as 1h10 = 70mins...
*/
private Rate(int hours, int minutes, int rate) {
this.minutes = minutes + hours * 60;
this.rate = rate;
}
public static Rate from(String timeStart, String timeEnd) {
LocalTime time1 = LocalTime.parse(timeStart.toUpperCase(), dateTimeFormatter);
LocalTime time2 = LocalTime.parse(timeEnd.toUpperCase(), dateTimeFormatter);
long minutesBetween = ChronoUnit.MINUTES.between(time1, time2);
for (int i = 0; i < Rate.values().length; i++) {
Rate r = Rate.values()[i];
if (r.minutes > minutesBetween) {
return Rate.values()[i-1];
}
}
return STOP0;
}
public String toString() {
return String.format("Rs.%s", rate);
}
}
public static void main(String... args) {
String timeStart = "09.30.00 am";
String timeEnd = "10.10.00 am";
System.out.println(Rate.from(timeStart, timeEnd));
}
}
I want to represent time with my time class. I can't use get and set methods.Only I can use listed methods on the code.But it doesn't work.
It returns 0:0:0.
public int addHours(int hours)
{
if(hours>=0&&hours<=23)
{
return hours;
}
return 0;
}
public int addMinutes(int minutes)
{
if(minutes>=0&&minutes<=59)
{
return minutes;
}
return 0;
}
public int addSeconds(int seconds)
{
if(seconds>=0&&seconds<=59)
{
return seconds;
}
return 0;
}
public String showTime()
{
return hours+":"+minutes+":"+seconds;
}
}
your code does nothing.
you need to do something like this:
public void addHours( int hours ){
this.hours += hours; // add hours
this.hours %= 24; // roll over at 24 hours
}
public void addMinutes( int minutes ){
this.minutes += minutes; // add minutes
addHours(this.minutes/60); // carry over to hours
this.minutes %= 60; // roll over at 60 minutes
}
public void addSeconds( int seconds ){
this.seconds += seconds; // add seconds
addMinutes(seconds/60); // carry over to minutes
this.seconds %= 60; // roll over at 60 seconds
}
(it probably won't matter, but this is not thread safe at all)
but this is generally a bad idea. Java 8 has a beautiful time api, pre Java-8 there is the JodaTime library (which is actually the basis of the Java 8 time api). It seems what you want to do could benefit from LocalTime:
LocalTime t = LocalTime.of(13,50,27).addHours(1).addMinutes(1).addSeconds(1);
System.out.println(t.toString());
// prints 14:51:28
Use java.util.Calendar and java.text.SimpleDateFormat:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, 0);
cal.add(Calendar.HOUR, 5);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(cal.getTime()));
Sorry for my english. I need to set time between 00:00:00 and 06:00:00, but my code doesn't work. I'm using joda library. My below method doesn't work, i can set time 14:00 or another, not not beetwen 00:00 and 6:00. What i'm doing wrong?
public void setTime(final TextView setText) {
String dateStart = "00:00:00";
String dateStop = "06:00:00";
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
DateTime dt1 = new DateTime(d1);
DateTime dt2 = new DateTime(d2);
int mHour = Hours.hoursBetween(dt1, dt2).getHours() % 24;
int mMinute = Minutes.minutesBetween(dt1, dt2).getMinutes() % 60;
TimePickerDialog tpd = new TimePickerDialog(context,
new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
setText.setText(String.valueOf(hourOfDay) + ":" + String.valueOf(minute));
}
}, mHour, mMinute, true);
tpd.show();
}catch(Exception e) {
Toast.makeText(getApplicationContext(), "Cant open time, sorry", Toast.LENGTH_SHORT).show();
Log.e("Time error", e.toString());
}
}
Have a look here, with mHour and mMinute, you are removing from the DatePicker the hours before 6:00:00; copying from the link here is the problem:
public TimePickerDialog (Context context, int themeResId,
TimePickerDialog.OnTimeSetListener listener, int hourOfDay, int
minute, boolean is24HourView)
Added in API level 1 Creates a new time picker dialog with the
specified theme.
Parameters:
context the parent context
themeResId the resource ID of the theme to apply to this dialog
listener the listener to call when the time is set
hourOfDay the initial hour
minute the initial minute
is24HourView Whether this is a 24 hour view, or AM/PM.
here it is, leave them t 0 and 0 if you want all hours and minutes in your picker
EDIT:
if you want to set time only between 0 and 6, look at this post
I have some documents and its created time is in milliseconds.
I need to separate them as Today, Yesterday, Last 7 Days, Last 30 Days, More than 30 Days.
I used the following code:convertSimpleDayFormat(1347022979786);
public static String convertSimpleDayFormat(Long val) {
long displayTime = System.currentTimeMillis() - val;
displayTime = displayTime/86400000;
String displayTimeVal = "";
if(displayTime <1)
{
displayTimeVal = "today";
}
else if(displayTime<2)
{
displayTimeVal = "yesterday";
}
else if(displayTime<7)
{
displayTimeVal = "last7days";
}
else if(displayTime<30)
{
displayTimeVal = "last30days";
}
else
{
displayTimeVal = "morethan30days";
}
return displayTimeVal;
}
I am subtracting the current time and passing the milliseconds and converting to one day.
But the issue I'm facing is, I couldn't calculate the exact time for the date in milliseconds.
I want to calculate for Today as: From Midnight 00:00 to Midnight 24:00. (Exactly for 24 hours.)
Similarly I want to exactly convert the Milliseconds into Today, Yesterday, Last 7 days, Last 30 Days and More than 30 Days.
private static Calendar clearTimes(Calendar c) {
c.set(Calendar.HOUR_OF_DAY,0);
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
c.set(Calendar.MILLISECOND,0);
return c;
}
public static String convertSimpleDayFormat(long val) {
Calendar today=Calendar.getInstance();
today=clearTimes(today);
Calendar yesterday=Calendar.getInstance();
yesterday.add(Calendar.DAY_OF_YEAR,-1);
yesterday=clearTimes(yesterday);
Calendar last7days=Calendar.getInstance();
last7days.add(Calendar.DAY_OF_YEAR,-7);
last7days=clearTimes(last7days);
Calendar last30days=Calendar.getInstance();
last30days.add(Calendar.DAY_OF_YEAR,-30);
last30days=clearTimes(last30days);
if(val >today.getTimeInMillis())
{
return "today";
}
else if(val>yesterday.getTimeInMillis())
{
return "yesterday";
}
else if(val>last7days.getTimeInMillis())
{
return "last7days";
}
else if(val>last30days.getTimeInMillis())
{
return "last30days";
}
else
{
return "morethan30days";
}
}
It's a small hack, not severely tested. Use at own risk. I've made it extensible so you can add new durations.
public static String prettyTimeStamp(long timeStamp) {
Calendar c = Calendar.getInstance();
c.clear(Calendar.HOUR_OF_DAY);
c.clear(Calendar.MINUTE);
c.clear(Calendar.SECOND);
c.clear(Calendar.MILLISECOND);
long today = c.getTimeInMillis();
final long oneDay = 24 * 60 * 60 * 1000L;
final long[] durations = new long[] { today - oneDay, today,
today + 7 * oneDay, today + 30 * oneDay };
final String[] labels = "Yesterday,Today,Last 7 days,Last 30 Days,More than 30 Days"
.split(",");
int pos = Arrays.binarySearch(durations, timeStamp);
return labels[pos < 0 ? ~pos : pos];
}
By the way, you should really just use a Library like PrettyTime