I am trying to display in a TextView when my application last updated (e.g., "Last updated at 12:13). I am trying to use a Calendar instance and I thought I understood it correctly but I seem to be having trouble. I know to get an instance I use the method Calendar.getInstance(). And then to get the hour and minute I was using Calendar.get(Calendar.HOUR) and Calendar.get(Calendar.MINUTE). My minute field returns correctly but Calendar.HOUR is returning the hour on a 24 hour clock and I want a 12 hour clock. I thought HOUR_OF_DAY was 24 hour clock. Where am I going wrong?
Here is the code I'm using:
Calendar rightNow = Calendar.getInstance();
mTv.setText("Refreshed! Last updated " +
rightNow.get(Calendar.HOUR) + ":" +
rightNow.get(Calendar.MINUTE) + ".");
mTv is my TextView that I'm updating. Thanks for any help.
Also, it would be ideal if I could say "Last updated 5 minutes ago." instead of "Last updated at 12:13pm". But I'm not sure the best way to have this update each minute without draining resources or the battery...?
I'd recommend using SimpleDateFormat in combination with the Date class for formatting the time:
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("K:mm a");
String formattedTime = sdf.format(now);
Short explanation how it works:
You create a SimpleDateFormat object and pass a String to it's construtor which tells it how to format every time/date object that gets passed to the format() function of it.
There are plenty of constants/letters which represent a special time object (e.g. seconds, an AM/PM marker, .. see the class documentation for the full list).
"K:mm a" means a "11:42 AM" format - one or two digits for the hour (depending on its value) in a 12 hour format, always two digits for minutes (mm) and either AM or PM (a), depending on the time.
After you did that, just pass a Date object to the format() function, and you'll get a formatted string. Note that a Date just holds one single point in time, if you create it from the constructor with no arguments ("= new Date()") it uses the current time. If you need another time, you can pass a long argument with the millis, you may get that from Calendar.getTimeInMillis().
As of implementing the "updated XY minutes ago function" - yes you'd have to update this every minute and you have to calculate the difference between the update and the current time. I'd say it's not worth it from a battery and extra work perspective.
If your app uses standard short update cycles (e.g. every hour or somthing along those lines) and is not fullscreen, the user has a visible clock on top/bottom of his screen. If he really wants to check how long it was since the update, he can take a short look and compare (mostly just minutes or hours/minutes). And IMHO thats no inconvinience for a user, at least it would not for me. I'd just compare without thinking about that. But I tend to kill apps which waste my battery for no useful reason.
Also note that not everybody uses a 12-hour format. To get a localized time format depending on users settings/country use DateFormat.getTimeInstance(). This returns a DateFormat, but this works like the SimpleDateFormat, just pass a time to format().
Use Calendar.HOUR_OF_DAY for 24h clock
Calendar rightNow = Calendar.getInstance();
mTv.setText("Refreshed! Last updated " +
rightNow.get(Calendar.HOUR_OF_DAY) + ":" +
rightNow.get(Calendar.MINUTE) + ".");
You can update editText in each minute using a thread like following
Thread t = new Thread(){
public void run() {
Calendar oldTime = Calendar.getInstance();
oldMinute = oldTime .get(Calendar.MINUTE);
while(true) {
Calendar rightNow= Calendar.getInstance();
newMinute = rightNow.get(Calendar.MINUTE);
if(newMinute != oldMinute) {
oldMinute = newMinute;
mTv.setText("Refreshed! Last updated " +
rightNow.get(Calendar.HOUR) + ":" +
rightNow.get(Calendar.MINUTE) + ".");
}
}
}
t.start();
Well, Calendar.get(Calendar.HOUR) should be returning 12-hour time, but if you wanted to produce your slightly nicer text, you can use the TimeUnit class for parsing simplicity.
long millis = Calendar.getInstance().getTimeInMillis();
String.format("Last updated %d min, %d sec ago.",
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
Related
I tried:
TimeZone.getDefault();
I tried:
Calendar mCalendar = new GregorianCalendar();
TimeZone mTimeZone = mCalendar.getTimeZone();
I tried:
Calendar c = Calendar.getInstance();
mTimeZone = c.getTimeZone();
No matter what I try... it gives me a default of 0 and GMT. My app just cannot seem to get the time zone (it should read -4 or ET, i.e. eastern USA time zones)
The strange thing is... my clock displays the correct time on my phone.
the "use automatic time zone" is checked in settings of my android device.
So why can't I get the local time in my app? how does the Android clock able to achieve this but not me?
I have checked online and cant seem to find anything. Is there at least a way to sync with the clock app and receive it's time to display on my app as well? Is there ANY way to get the correct time on my app?
System.getMilliseconds() return the time since epoch, which would only function as the current time in areas that use GMT. (As long as what you are using doesn't make it's own conversion)
To get local time in milliseconds since epoch, you can use this function:
// Kotlin
fun getLocalTime(): Long
{
val currentDate = Calendar.getInstance()
return currentDate.timeInMillis + TimeZone.getDefault().getOffset(currentDate.timeInMillis)
}
Which in Java would probably look like this:
// Java
static long getLocalTime()
{
Calendar currentDate = Calendar.getInstance();
return currentDate.getTimeInMillis() + TimeZone.getDefault().getOffset(currentDate.getTimeInMillis());
}
The function takes the time since epoch and adds to it the timezone offset of the phone's local timezone.
I tried a lot with different methods to find out exact solution, but I only get time difference, if I know future date but I want Next Sunday time from current time.
You can try this,
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int saturdayInMonth = calendar.get(Calendar.DAY_OF_MONTH) + (Calendar.SATURDAY - calendar.get(Calendar.DAY_OF_WEEK));
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
saturdayInMonth, 23, 59, 59); // This time will be sunday night 23 hour 59 min and 59 seconds
Date sunday = new Date(calendar.getTimeInMillis() + 1000); //this is 1 second after that seconds that is sunday 00:00.
In Android, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes, together with ThreeTenABP (more on how to use it here). All the classes are in the org.threeten.bp package.
To get a difference between 2 dates, you could use a org.threeten.bp.ZonedDateTime, because this class takes care of Daylight Saving Time changes (and any other offset changes that might happen) and gives the correct/accurate result (if you calculate it without using a timezone, DST changes won't be considered in the calculation).
I also use org.threeten.bp.temporal.TemporalAdjusters class, which has a built-in method to find the next specified day-of-week (by using the constants in the org.threeten.bp.DayOfWeek class).
To get the difference, you can use org.threeten.bp.temporal.ChronoUnit.MILLIS to get the difference in milliseconds (and then you use this value to display in whatever format you want). Or you can use another constants available in org.threeten.bp.temporal.ChronoUnit class (such as MINUTES or HOURS, which will give the difference in minutes or hours - check the javadoc to see all units available).
Another way to get the difference is using a org.threeten.bp.Duration which will contain the number of seconds and nanoseconds between the 2 dates.
// change this to the timezone you need
ZoneId zone = ZoneId.of("Asia/Kolkata");
// get current date in the specified timezone
ZonedDateTime now = ZonedDateTime.now(zone);
// find next Sunday
ZonedDateTime nextSunday = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
// get the difference in milliseconds
long diffMillis = ChronoUnit.MILLIS.between(now, nextSunday);
// get the difference as a Duration
Duration duration = Duration.between(now, nextSunday);
Note that I used the timezone Asia/Kolkata. The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like IST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
The code above will get nextSunday with the same time (hour/minute/second/nanosecond) as now - except when there's a DST change (in this case, the time is adjusted accordingly).
But if you want to get the remaining time from now until the beginning of the next Sunday, then you have to adjust it to the start of the day before calculating the difference:
// adjust it to the start of the day
nextSunday = nextSunday.toLocalDate().atStartOfDay(zone);
Note that the start of a day is not always midnight - due to DST changes, a day can start at 01:00 AM for example (clocks might be set to 1 hour forward at midnight, making the first hour of the day to be 1 AM). Using atStartOfDay(zone) guarantees that you don't have to worry about that, as the API handles it for you.
If the current date is already a Sunday, what's the result you want?
The code above will get the next Sunday, even if the current date is a Sunday. If you don't want that, you can use TemporalAdjusters.nextOrSame, which returns the same date if it's already a Sunday.
To display the Duration value in time-units (like hours, minutes and seconds), you can do the following:
StringBuilder sb = new StringBuilder();
long seconds = duration.getSeconds();
long hours = seconds / 3600;
append(sb, hours, "hour");
seconds -= (hours * 3600);
long minutes = seconds / 60;
append(sb, minutes, "minute");
seconds -= (minutes * 60);
append(sb, seconds, "second");
append(sb, duration.getNano(), "nanosecond");
System.out.println(sb.toString());
// auxiliary method
public void append(StringBuilder sb, long value, String text) {
if (value > 0) {
if (sb.length() > 0) {
sb.append(" ");
}
sb.append(value).append(" ");
sb.append(text);
if (value > 1) {
sb.append("s"); // append "s" for plural
}
}
}
The result (in my current time) is:
47 hours 44 minutes 43 seconds 148000000 nanoseconds
If you want the milliseconds instead of nanoseconds, you could replace append(sb, duration.getNano(), "nanosecond") with:
// get milliseconds from getNano() value
append(sb, duration.getNano() / 1000000, "millisecond");
I have a TimePickerDialog which lets the user pick a time. The TimePickerDialog has a onTimeSet method that gets called when the user finished picking the time.
I pass the arguments to a second method, setTime(int hour, int minute) which saves the values and displays a formatted time.
Here is a code snippet of the method:
java.text.DateFormat dateFormatter =
java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT, Locale.getDefault());
DateTime dt = new DateTime();
dt = dt.hourOfDay().setCopy(hour);
dt = dt.minuteOfHour().setCopy(minute);
String text = dateFormatter.format(dt.toDate());
The Problem is that (sometimes, not always) the hour value is off by one or maybe even two hours. I think the cause of the problem has something to do with timezones, but I do not know what the exact cause is. I also think that the problem is caused by the Joda DateTime object, since I did not have any issues before I implemented Joda time AND because it also gets saved with one hour off.
Any ideas what happens / how to fix it?
For this answer, I'm using joda-time 2.7 (although it might work with previous versions).
I'm also assuming that your program only cares about hour and minute (I'm not an Android expert, but I saw docs from TimePickerDialog and it seems to be the case).
So, if you're manipulating only hour and minute, you don't need to use DateTime class (actually you shouldn't in this case).
That's because a DateTime object is "aware" of all date fields, including day, month, year and timezone. So, when you create a new DateTime(), it creates a new object with current date and time in your default timezone. And if the current date in default timezone is in summer time (aka daylight saving time), you can have these hour shifts.
(And I believe that Android takes the default timezone from the device's system, so it can vary according to the device running the code - at least that's how it works in computers, so it shouldn't be different for devices).
As you don't need to know day/month/year and timezone, you can use LocalTime class (org.joda.time.LocalTime) which is a class with only hour and minute fields (and seconds, if you want; if you don't care about seconds, they'll be set to zero). And the best part is: this class doesn't care about timezones, so 10:00 AM will always be 10:00 AM.
You also don't need to use java.text.DateFormat, as joda-time has its own formatters. So the code will be like this:
public void setTime(int hour, int minute) {
// shortTime() is equivalent to DateFormat.SHORT
DateTimeFormatter fmt = DateTimeFormat.shortTime().withLocale(Locale.getDefault());
LocalTime time = new LocalTime(hour, minute);
String text = fmt.print(time);
System.out.println(text);
}
Doing some tests (assuming default locale is en_US):
setTime(9, 30); // prints 9:30 AM
setTime(10, 0); // prints 10:00 AM
PS: the output may vary according to your default Locale (which I also believe it comes from the device's system). If you want a fixed format (independent from locales), you can use DateTimeFormat.forPattern("h:mm a"), which also results in the output above (and when you use formatters this way, the default locale doesn't change the output).
I know this is very simple question but I am not able to do it.
I have a code that gets current time but this time is not accurate.
booking.CreateDateTime = DateTime.Now.ToUniversalTime();
When I am booking at 12:00 then in database stores 1:00 that means 1 hour difference.
How can I get accurate time?
Use System.currentTimeMillis() to get the current GMT time in mili seconds since epoch.
Then you can use this value to create a new Date or Calendar object and localize it wherever the user is.
I'm not familiar with what you have there, but ToUniversalTime suggests to me that this is adjusting your time to some fixed time zone (probably GMT)
Use a Date to get the time right now, and then a Calendar to do any time zone changes on it that you want.
Example, assuming CreateDateTime is actually a string of what you said it was:
Date date = new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
booking.CreateDateTime = calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
i want an alarm to go off when user checks in a checkbox. Here is my code:
if (cb1.isChecked())
{
Calendar calA = Calendar.getInstance();
//calA.set(Calendar.YEAR, Calendar.YEAR);
//calA.set(Calendar.MONTH, Calendar.MONTH);
//calA.set(Calendar.DAY_OF_MONTH, Calendar.DAY_OF_MONTH);
calA.set(Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY);
calA.set(Calendar.MINUTE, Calendar.MINUTE);
calA.set(Calendar.SECOND, Calendar.SECOND);
calA.set(Calendar.MILLISECOND, Calendar.MILLISECOND);
alarmManager.set(AlarmManager.RTC_WAKEUP, calA.getTimeInMillis(), pendingIntentA);
Toast.makeText(main.this, "Set time: " + String.valueOf(calA.getTime()), Toast.LENGTH_SHORT).show();
}
Other codes are working fine, and if i set the hour and minute to specific ones, like
calA.set(Calendar.HOUR_OF_DAY, 15);
calA.set(Calendar.MINUTE, 24);
it's working, but with this code i always get this toast message:
Sat Mar 05 11:12:00 or Sat Mar 05 11:12:13
(neither the date nor the time is good)
What is wrong with my code?
Calendar.HOUR_OF_DAY is a constant, which just so happens to be an integer.
When you
calA.set(Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY);
you are in fact setting the hour of day to whatever number happens to have been chosen for this constant. This value has no real meaning in relation to the hour of day, so it'll produce a garbage result.
When you get the calendar, it's by default set to the current time, so if that's what you're going for, simply don't set the time:
Like other locale-sensitive classes, Calendar provides a class method, getInstance, for getting a generally useful object of this type. Calendar's getInstance method returns a Calendar object whose calendar fields have been initialized with the current date and time:
Calendar rightNow = Calendar.getInstance();
If you then want to set a time like "5 minutes into the future", do something like:
calA.add(Calendar.MINUTE, 5);
If you still get an incorrect time, verify that the system time is set correctly.
Source:
Calendar documentation
Calendar calA = Calendar.getInstance(); returns a calendar object whose locale is based on system settings and whose time fields have been initialized with the current date and time.
Sebastian P is right that Calendar.HOUR_OF_DAY is a constant, a key/index used for referencing the actual hour value.
See http://developer.android.com/reference/java/util/Calendar.html