I want to find difference between 2 timestamps. What I am doing is storing 1st timestamp in shared prefs
and try to subtractt it from the new timestamp. To get timestamp, I am using -
public static String setTimestamp() {
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return dateFormat.format(new Date());
} catch (Exception e) {
return null;
}
}
How do I subtract 2 timestamps and check if the difference is smaller than 120 seconds?
You can find difference like this
long diffInMs = firstTimestamp - secondTimestamp;
long diffInSec = TimeUnit.MILLISECONDS.toSeconds(diffInMs);
Now you have got difference in seconds so just go ahead and check your condition
if(diffInSec < 120){
}
I suggest the following for getting a string for saving into your shared preferences:
String timestampToSave = Instant.now().toString();
Now to count the seconds since the time given in that string:
String timestampFromSharedPreferences = mySharedPrefs.getString(KEY, null);
long diffInSeconds = Duration.between(Instant.parse(timestampFromSharedPreferences),
Instant.now())
.getSeconds();
if (diffInSeconds < 120) {
System.out.println("Less than 120");
}
An Instant is an unambiguous point in time independent of time zone. Its string representation goes like 2018-04-16T09:26:27.929Z (ISO 8601). The Z in the end means UTC. So the above works even in the off case where the user changes the time zone setting of the device, or some other part of your program changes the time zone setting of your JVM. You notice that we do not need an explicit formatter for formatting the string and parsing it back into an Instant.
In case you want to compare to 2 minutes rather than 120 seconds, use toMinutes() instead of getSeconds().
In case you cannot change the string saved in shared preferences, you will need to cross you fingers that the time zone setting hasn’t been changed and then parse the string like this:
DateTimeFormatter timestampFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
Instant storedTimestamp = LocalDateTime.parse(timestampFromSharedPreferences, timestampFormatter)
.atZone(ZoneId.systemDefault())
.toInstant();
Now let Duration calculate the difference between the Instant objects as before.
I am using and recommending java.time, the modern Java date and time API. The SimpleDateFormat class that you were using is long outdated along with Date and is also notoriously troublesome. The modern API is so much nicer to work with.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
Related
I'm stuck with the daylight problem in android the time should be +3 GMT/UTC
but I'm getting only +2. is there any solution or I can't handle it? please find below my code
TimeZone.getDefault().useDaylightTime();
SimpleDateFormat df = new SimpleDateFormat("HH:mm",Locale.ENGLISH); //"2021-02-18T11:00:00"
df.setTimeZone(TimeZone.getTimeZone("UTC"));
return df.format(calendar.getTime());
Note that the DST OFFSET is returning zero. what should I do to handle daylight?
Another note my time is Jordan / Amman,
In winter this should return +2 but in summer it should return +3
java.time
Consider using java.time, the modern Java date and time API, for your date and time work. Let’s first declare a formatter for your desired time format:
private static final DateTimeFormatter TIME_FORMATTER
= DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);
Now you may format the time from your Calendar in this way:
// Assume you are getting a Calendar from somewhere
Calendar calendar = new GregorianCalendar();
ZonedDateTime dateTime = calendar.toInstant().atZone(ZoneId.systemDefault());
String dateTimeString = dateTime.format(TIME_FORMATTER);
System.out.println(dateTimeString);
I ran the code just now, that is, 16:33 in UTC or 19:33 in Jordan. The output was:
19:33
If you don’t depend on getting on old-fashioned Calendar from somewhere, it’s probably even simpler and cleaner. For example, to get the current time in your time zone:
String timeString
= LocalTime.now(ZoneId.systemDefault()).format(TIME_FORMATTER);
System.out.println(timeString);
What went wrong in your code?
You set the time zone of your SimpleDateFormat to UTC. So the time in UTC was printed regardless of your default time zone. And since UTC hasn’t got summer time (DST), no such was taken into account.
BTW, this method call of yours does nothing:
TimeZone.getDefault().useDaylightTime();
From the documentation:
Returns:
true if this TimeZone uses Daylight Saving Time, false,
otherwise.
So the method does not alter anything and certainly not the UTC time zone. It only queries whether the mentioned time zone uses summer time (daylight saving time). So since the Asia/Amman time zone does, it should return true in your case.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
I have an UTC datetime in the format 2019-12-06T06:04:50.022461Z I want to convert into readable datetime in the format dd-mm-yyyy hh:mm:ss. I am not able to convert in the particular format. Any help will be highly appreciated. Thanks
java.time and ThreeTenABP
I am assuming that you want to display the time in your user’s time zone. As you said already, your string is in UTC, and very few users will be happy to read the time in UTC.
DateTimeFormatter readableFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss");
String originalString = "2019-12-06T06:04:50.022461Z";
String readableString = Instant.parse(originalString)
.atZone(ZoneId.systemDefault())
.format(readableFormatter);
System.out.println(readableString);
For the sake of the example I ran this code in America/Sitka time zone. Output was:
05-12-2019 21:04:50
If you did want to display the time in UTC as in the original string:
String readableString = OffsetDateTime.parse(originalString)
.format(readableFormatter);
06-12-2019 06:04:50
Don’t go with the classes SimpleDateFormat, TimeZone and Calendar used in the currently accepted answer. They are all poorly designed, SimpleDateFormat in particular is a notorious troublemaker and also cannot parse 6 decimals on the seconds as in your string. Those three classes are also all long outdated. Instead I am using java.time, the modern Java date and time API. It is so much nicer to work with. The code is not only shorter, I think that you will also find it clearer to read (either immediately or when you get used to the fluent style).
I am exploiting the fact that your original string is in ISO 8601 format. The classes of java.time parse ISO 8601 format as their default, that is, without any explicit formatter.
For the vast majority of purposes you shold not want to convert from one string format to another, though. Inside your program keep your date and time as an Instant or other proper date/time object. only convert to a string when a string is needed in the interface.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
You can use SimpleDateFormat to format the date. Check below:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(sdf.parse("2019-12-06T06:04:50.022461Z"));
} catch (Exception ex) {
ex.printStackTrace();
}
SimpleDateFormat returnFormat = new SimpleDateFormat("dd-mm-yyyy hh:mm:ss");
returnFormat.format(calendar.getTime());
You can try this in java 8
String dateString = "2019-12-06T06:04:50.022461Z";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC);
TemporalAccessor date = fmt.parse(dateString);
Instant time = Instant.from(date);
DateTimeFormatter fmtOut = DateTimeFormatter.ofPattern("dd-mm-yyyy hh:mm:ss").withZone(ZoneOffset.UTC);
String newDateString = fmtOut.format(time);
I want to get two timestamps in LDAP format one has to be the beginning of the day and other has to be end of the day. It can be done by using Java 8 (using Joda-Time) but is there a way out using lower version like java 7.
This is the closest solution I found online, but I do not know how to get the timestamp of start of the day and end of the day. Additionally I need to check for 15 days back (start of the day end of the day from current system time)
To convert a Win32 filetime string to Date, use:
long fileTime = (Long.parseLong(inputDateString) / 10000L) - + 11644473600000L;
Date inputDate = new Date(fileTime);
To convert a Date to Win32 filetime, use:
long fileTime = (inputDate.getTime() + 11644473600000L) * 10000L;
String outputDate = Long.toString(fileTime);
e.g. 131220409910000000 will be converted to 2016/10/27 14-23-11 and vice versa
Check this url for a nice online epoch/filetime converter:
http://www.epochconverter.com/ldap
java.time and ThreeTen Backport
Instant ldapEpoch = Instant.parse("1601-01-01T00:00:00Z");
ZoneId zone = ZoneId.of("America/Port-au-Prince");
LocalDate date = LocalDate.now(zone);
Instant startOfDay = date.atStartOfDay(zone).toInstant();
Duration sinceLdapEpoch = Duration.between(ldapEpoch, startOfDay);
assert sinceLdapEpoch.getNano() == 0 : sinceLdapEpoch;
long ldapTimestamp = sinceLdapEpoch.getSeconds() * 10_000_000;
System.out.println(ldapTimestamp);
Output is (tested on jdk1.7.0_67):
132114384000000000
The start of the day differs from time zone to time zone. I have used America/Port-au-Prince as an example, you need to make your own pick. Use ZoneOffset.UTC if that is what you require.
For the end of the day use date.plusDays(1) instead of date in the same calculation. That will give you the first moment of the following day. Can you have the last moment of the current day instead? No, and you shouldn’t want to either. There is no last moment of a day. A day is a half-open time interval from the first moment of the day inclusive to the first moment of the next day exclusive. The best and the correct way to do in programming is to handle it as such (you may of course cheat and subtract 1 from the result you get to obtain the last possible LDAP timestamp of the day, not recommended).
I am using java.time, the modern Java date and time API. We don’t want to use Date or Calendar or other of the poorly designed and long outdated date and time classes in Java. java.time is so much nicer to work with.
Question: is there a way out using lower version like java 7?
Yes, java.time works nicely on Java 7. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
You could try the following:
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c.clear();
c.set(2016, 4, 22); //your date
long time1= c.getTimeInMillis();
c.set(1601, 0, 1);
long time2= c.getTimeInMillis();
long ldap = (time1- time2) * 10000;
I have a date: actDate, and its time was extracted as string timeFromAct
Then I have a reference time from database: timeValue, this was converted to string as timeFromDB
DateFormat formatTime;
formatTime = new SimpleDateFormat("HH:mm:ss");
Date actDate = actinfo.getActDate();
String timeFromAct = formatDay.format(actDate);
String date= ListOfConstants.SOME_DATE_REF;
ResultTable[] timeValue = RTManager.getSomethingDecodeList(date);
String timeFromDB = Arrays.toString(timeValue);
I know converting the two as Strings won't let me compare the 2 times but
I would like to know how do I compare these time values in an if statement (similar to below comparison)?
if (timeFromAct is greater than or equal to timeFromDB){
*some codes*
}
Write like this ;
if (actDate.after(timeFromDb) || actDate.compareTo(timeFromDB)==0 ){
*some codes*
}
In detail
actDate.after(timeFromDb) provides greater than case.
actDate.compareTo(timeFromDB)==0 provides equality of actDate and
timeFormDb.
Or in String comparasion if both are same format ;
if(timeFromAct.compareTo(timeFromDB) > 0 || timeFromAct .equals(timeFromDB)){..}
or more simple
if(!(timeFromAct.compareTo(timeFromDB) < 0)){..}
String.compareTo works as
"a".compareTo("b"); // returns a negative number, here -1
"a".compareTo("a"); // returns 0
"b".compareTo("a"); // returns a positive number, here 1
LocalTime from java.time
Date actDate = actinfo.getActDate();
ResultTable[] timeValue = RTManager.getSomethingDecodeList(date);
LocalTime actualTime = actDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalTime();
if (timeValue.length == 1) {
LocalTime timeFromDB = LocalTime.parse(timeValue[0].toString());
if (! actualTime.isBefore(timeFromDB)) {
System.out.println("timeFromAct is greater than or equal to timeFromDB");
} else {
System.out.println("timeFromAct is less than timeFromDB");
}
} else {
System.out.println("Unexpected number of ResultTable entries: " + timeValue.length);
}
A LocalTime is a time of day without date and without time zone. I believe that this is exactly what you need.
I have assumed that getActDate invariably returns an old-fashoined Date object. It would be better if you can modify it to return an appropriate type from java.time, the modern Java date and time API.
In the conversion from Date to LocalTime in the above code you will need to get your time zone right, or you will get incorrect results. I have tentatively assumed the JVM time zone setting, notated as ZoneId.systemDefault(), since the SimpleDateFormat in your question used this; but this is fragile since the setting can be changed from another part of your program or another program running in the same JVM. Better if you can specify the correct time zone like for example ZoneId.of("Asia/Manila").
Do check your assumptions. RTManager.getSomethingDecodeList will surely return only 1 value like this: [23:32:45]. The check costs so little, and it will be expensive to track down the bug if some day a new programmer on your project modifies it to return an array of a different length. Do help by issuing a helpful error message in this case.
The date-time classes that you used — DateFormat, SimpleDateFormat and Date — are long outdated and poorly designed. The first two in particular are renowned for being troublesome. I see no reason why you should want to use any of those if you can avoid it.
unfortunately i cannot import java.time from where i'm doing the codes.
If you are using at least Java 6, you can use java.time.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
SimpleDateFormat to = new SimpleDateFormat("MM/dd/yyyy Z");
Date date = from.parse("2017-08-10T00:00:00.000+0000");
String newDateStr = to.format(date);
The newDateStr is 08/09/2017 -0500. I expect that newDataStr can have the same timezone as the original date string(0000) -- 08/10/2017 -0000. What should I do to achieve this?
Preserving the offset from the original string is much easier with java.time, the modern Java date and time API:
DateTimeFormatter from = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZ");
DateTimeFormatter to = DateTimeFormatter.ofPattern("MM/dd/yyyy Z");
String newDateStr = OffsetDateTime.parse("2017-08-10T00:00:00.000+0000", from)
.format(to);
System.out.println(newDateStr);
This prints
08/10/2017 +0000
This is not the only reason for recommending changing to the modern API. The Date class that you are using is long outdated, and SimpleDateFormat in particular is renowned for being troublesome to work with. I always recommend staying away from those classes in 2018. The modern API is generally much nicer. And since you are already using Java 8, there is absolutely no reason why you shouldn’t want it (for anyone reading along and using Java 6 or 7, the new API has been backported to those Java versions too).
What went wrong?
An old-fashioned Date object is just a point in time, it doesn’t hold a time zone or offset in it. So after you had parsed your string into a Date, the offset information was no longer there. So neither the Date nor to, the new formatter, had any way of knowing which offset or time zone had been in the original string. Instead, the new formatter used its own time zone. Since you had not explicitly set a time zone on the formatter, its time zone was that of your JVM, which apparently was a time zone that was on offset -5 from UTC on these days of September 2017.
There are tricky ways to solve the problem with the outdated classes, but as I have probably said already, I wouldn’t want to bother.
"Call requires API Level 26" for Android
#Ponomarenko Oleh in a comment writes:
Pay attention: "Call requires API Level 26" for Android.
However, java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in. This is also the intended meaning of the message quoted in the comment.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
You could use the Java 8 Date API which provides a good set of functionality
to convert dates into strings (including timezone support).
An example:
ZonedDateTime dateTime = ZonedDateTime.parse("2017-08-10T00:00:00.000+0000", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
String newDateStr = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy Z"));
For more information you can look at:
How to parse/format dates with LocalDateTime? (Java 8)
https://www.mscharhag.com/java/java-8-date-time-api