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?
Related
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);
I want to test current time.
Is it the same between the two times?
-With the note, I've already done a job
function to enter the start time
and the time to end.
Now i want to complete the special function.
i'm testing this entry value between the two times.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int hourStart = 5;
int minuteStart = 30;
String PMAMStart="AM";
int hourEnd = 6;
int minuteEnd = 30;
String PMAMEnd="AM";
boolean checkTime= checkCurrentTimeBetweenTowVlue(hourStart,minuteStart,PMAMStart,hourEnd,minuteEnd,PMAMEnd);
}
private boolean checkCurrentTimeBetweenTowVlue(int hStart,int mStart,String ampmStart,int hEnd,int mEnd,String ampmEnd){
Calendar cal = Calendar.getInstance();
return false;
}
}
In your case, you can set the individual calendar fields such as AM_PM, Hour, and Minute for both start and end dates, convert the time to minutes, and then find the difference between the times. Here is the solution:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int hourStart = 5;
int minuteStart = 30;
String PMAMStart="AM";
int hourEnd = 6;
int minuteEnd = 30;
String PMAMEnd="AM";
boolean checkTime= checkCurrentTimeBetweenTwoValues(hourStart,minuteStart,PMAMStart,hourEnd,minuteEnd,PMAMEnd);
if (checkTime) {
System.out.println("Time is Same");
} else {
System.out.println("Time is not Same");
}
}
private boolean checkCurrentTimeBetweenTwoValues(int hStart,int mStart,String ampmStart,int hEnd,int mEnd,String ampmEnd){
Calendar startCalendar = Calendar.getInstance();
Calendar endCalendar = Calendar.getInstance();
if (ampmStart.equalsIgnoreCase("AM")) {
startCalendar.set(Calendar.AM_PM, 0);
} else {
startCalendar.set(Calendar.AM_PM, 1);
}
startCalendar.setTimeZone(TimeZone.getDefault());
startCalendar.set(Calendar.HOUR, hStart);
startCalendar.set(Calendar.MINUTE, mStart);
if (ampmEnd.equalsIgnoreCase("AM")) {
endCalendar.set(Calendar.AM_PM, 0);
} else {
endCalendar.set(Calendar.AM_PM, 1);
}
endCalendar.setTimeZone(TimeZone.getDefault());
endCalendar.set(Calendar.HOUR, hEnd);
endCalendar.set(Calendar.MINUTE, mEnd);
long timeDifference = TimeUnit.MILLISECONDS.toMinutes(
Math.abs(endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis()));
System.out.println(("Time Difference: " + timeDifference));
return (timeDifference == 0);
}
}
You can also use TimeUnit.MILLISECONDS.toSeconds to check for Seconds but for that, you need to set the Seconds component of the Calendar instance.
Regards,
AJ
If you can use Java 8 (beginning with API level 26 in Android) or if you are willing / able / allowed to import a very useful library that enables java.time support to lower API levels, then the following might be a neat solution:
public static boolean isNowBetween(int startHour, int startMinute, int endHour, int endMinute) {
LocalTime start = LocalTime.of(startHour, startMinute);
LocalTime end = LocalTime.of(endHour, endMinute);
LocalTime now = LocalTime.now();
return now.isAfter(start) && now.isBefore(end);
}
Get current minutes and hours from cal object. Convert start, end, current time into minutes, then it will be easy to compare.
private boolean checkCurrentTimeBetweenTowVlue(int hStart,int mStart,String ampmStart,int hEnd,int mEnd,String ampmEnd){
Calendar cal = Calendar.getInstance();
int hours = cal.get(Calendar.HOUR_OF_DAY);
int minutes = cal.get(Calendar.MINUTE);
if(ampmStart.equals("PM")){
hStart += 12;
}
int minutes_start = hStart*60 + mStart;
if(ampmEnd.equals("PM")){
hEnd += 12;
}
int minutes_end = hEnd*60 + mEnd;
int minutes_curr = hours*60 + minutes;
if(minutes_curr>minutes_start && minutes_curr<minutes_end){
return true;
}
return false;
}
Android Timepickerdialog is changing hours illogically when I'm scrolling minutes. I have set the minute interval to 30 minutes in my timepickerdialog so the values for minutes are 00 and 30. For example when I set the hours to 00 and change minutes to from 00 to 30 the hours are decreased one hour so the time is now 23:30 and what I'm suppose to have is 00:30. I realized that this doesn't happen on Samsung devices but happens on every other manufacturers devices. Is there any way to disable hours change when scrolling the minutes?
Here is my code
public class CustomTimePickerDialog extends TimePickerDialog {
private int TIME_PICKER_INTERVAL = 30;
private TimePicker mTimePicker;
private final OnTimeSetListener mTimeSetListener;
public int interval1 = 1;
public CustomTimePickerDialog(Context context, OnTimeSetListener listener,
int hourOfDay, int minute, boolean is24HourView, int interval) {
super(context, TimePickerDialog.THEME_HOLO_LIGHT, null, hourOfDay,
minute / interval, is24HourView);
TIME_PICKER_INTERVAL = interval;
mTimeSetListener = listener;
}
#Override
public void updateTime(int hourOfDay, int minuteOfHour) {
mTimePicker.setCurrentHour(hourOfDay);
mTimePicker.setCurrentMinute(minuteOfHour / TIME_PICKER_INTERVAL);
}
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case BUTTON_POSITIVE:
if (mTimeSetListener != null) {
mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute() * TIME_PICKER_INTERVAL);
}
break;
case BUTTON_NEGATIVE:
cancel();
break;
}
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
Class<?> classForid = Class.forName("com.android.internal.R$id");
Field timePickerField = classForid.getField("timePicker");
mTimePicker = (TimePicker) findViewById(timePickerField.getInt(null));
Field field = classForid.getField("minute");
NumberPicker minuteSpinner = (NumberPicker) mTimePicker
.findViewById(field.getInt(null));
minuteSpinner.setMinValue(0);
minuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<String>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
minuteSpinner.setDisplayedValues(displayedValues
.toArray(new String[displayedValues.size()]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I know there is at least one similar question but it doesn't have problem solving answer.
Android time picker auto change hours when minutes get scrolled
EDIT: I also noticed that when I changed the minute interval to 15 it's working great. For example when I'm increasing the minutes from 45 to 00 the hours are increased by one. Same thing backwards when I'm decreasing minutes from 00 to 45 the hours are decreased by one. Same thing when the minute interval is 6. So the problem is only with the 30 minute interval and it is necessary for me to have that 30 minute interval in my software.
I solved it like below. Just call minute changed listener after minuteSpinner.setDisplayedValues()
minuteSpinner.setOnValueChangedListener { picker, oldVal, newVal ->
// Declare this listener to prevent hour change
}
I've been looking for the same problem as you and couldn't find a way. So I tried this and that by myself and found the simplest solution!
So I'm starting to get really interested about Threads and how it works, Kinda amazing how it works but I just learned about it today and trying to make a program to work. So im trying to make a clock that gives me in a Jlabel a current clock which is right now and a Textfield where I enter the time by myself. so what I want to do is it should start by showing me the time, when pressing the button "Set time" it should change the time as I entered and go from there as a clock.
So my problem right now is that whenever I press the Set time now it changes for a second and then turn back to the current clock again. and I don't really know how to stop the first thread when pressing Set time (Which starts the second Thread)
However I think this is kinda simple but fun to work with,
EDIT: I Also found out that I will have a problem by counting when entering a own "clock". My code:
public Clock() {
initialize();
Thread1();
}
.......
JButton btnSetTime = new JButton("Set time");
btnSetTime.setBounds(474, 262, 89, 23);
frame.getContentPane().add(btnSetTime);
btnSetTime.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnSetTime) {
Thread2();
}
}
});
}
public void Thread2() {
Thread t2 = new Thread() {
public void run() {
try {
for(;;) {
int hour = Integer.parseInt(tfhour.getText());
int minute = Integer.parseInt(tfminute.getText());
int second = Integer.parseInt(tfsecond.getText());
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};t2.start();
}
public void Thread1() {
Thread t1 = new Thread() {
public void run() {
try {
for(;;) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};t1.start();
}
}
So as I can see, the int hour = Integer.parseInt(tfhour.getText()); will probably not count as a Clock if I change to my own clock later on if i'm right? In that case, How can I fix it?
I hope I have all my problems out here in the post and I hope anyone here is willing to help me aswell :)
EDIT:
To make it easier to see:
EDIT PART 3:0
You have to define a global variable to stop the thread 1, when the thread 2 starts. Here is an example,
//define a variable that controls the thread 1
static boolean clockSet = false;
Now thread 1 is written such as it runs only when the clockSet is false, that is clock not set by a click.
Thread t1 = new Thread(){
public void run(){
while(!clockSet){
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
In your thread 2, set the clockSet to true, so the thread 1 will stop. I see you are just displaying the value entered, but not setting those on a Calendar object. So create a Calendar object in thread 2, set the user defined values, and increment the time after every second of sleep.
Thread t2 = new Thread(){
public void run(){
clockSet = true;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(tfhour.getText()));
cal.set(Calendar.MINUTE, Integer.parseInt(tfminute.getText()));
cal.set(Calendar.SECOND, Integer.parseInt(tfsecond.getText()));
while(true){
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
try {
sleep(1000);
cal.add(Calendar.SECOND, 1);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
};
Have fun..!
Sure, you see the code
try {
for(;;) {
int hour = Integer.parseInt(tfhour.getText());//this one
int minute = Integer.parseInt(tfminute.getText());//and this one
int second = Integer.parseInt(tfsecond.getText());//and this too
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
you are setting hour, minute & second each and every time inside the for loop. So the clock is reseting.
Make them to get initialize only once, i.e. take them out of the loop.
Further this code
for(;;) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
is making your timer work as clock and not a timer because after 1 sec. the hour, minute & second are set to the values according to the time you get from Calendar.
Due to this your code will work as a clock that show the current time.
In my opinion you don't need the second thread at all. What I would do in this case is create three Int fields, hour-, minute- and second-offset, which you change when the button is pressed to, for example, hourOffset = Calendar.HOUR_OF_DAY - Integer.parseInt(tfhour.getText())%24; (example for the hours). Than you just need to add the offset to the time in thread1, which allways works since you start with 0 as offset.
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