I have the following JSON entries in a .json file that I am reading in.
There are numerous JSON entries and each hold the same format. The initial two values specify the date and month:
[["1","12","06:26","08:03","12:09","13:46","14:17","16:05","17:42"]
So the initial "1" and "12" will equate to the 1st of December.
Can someone help me write a method where as soon as the JSON is read in, the device will use the device day/month to check which JSON array to display on the app screen?
I’m no expert in JSON but I do know about days and months. So here’s how to check whether those two values from the JSON array denote today’s date according to your device:
MonthDay today = MonthDay.now(ZoneId.systemDefault());
try {
if (MonthDay.of(Integer.parseInt("12"), Integer.parseInt("1")).equals(today)) {
System.out.println("This is the array to display today");
}
} catch (NumberFormatException nfe) {
System.out.println("Day or month from array was not a number: " + nfe.getMessage());
}
I am using and recommending java.time, the modern Java date and time API.
ZoneId.systemDefault() is my attempt to get the device’s time zone setting. Beware, however, that I only get the JVM’s time zone setting, it’s not always the same. For example, the JVM setting may have been changed by other parts of your program or by another program running in the same JVM.
How to get those strings from each JSON array also depends on what library you are using for parsing your JSON.
Question: Can I use java.time on Android?
Yes, you can use java.time on Android. It just requires at least Java 6.
In Java 8 and later and on newer Android devices 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.
First of all, to retrieve the current day and month, I would use the following code:
Calendar instance = Calendar.getInstance();
currentMonth = instance.get(Calendar.MONTH);
currentDay = instance.get(Calendar.DAY);
int month=currentMonth+1;
After this, you need to get the data out of the json string by creating a json array, then a json object and filter the specifically needed string (day and month) out of the string.
JSONArray arr = new JSONArray(result);
JSONObject jObj = arr.getJSONObject(0);
String day = jObj.getString("Day");
String month = jObj.getString("Month");
Now, put all dates you have in arrays.
And then, simple compare all of the given dates with the current one.
Problem is, that you do not have prefixes like that:
[{"Date":"2012-1-4T00:00:00","keywords":null, ... }]
These are needed to tell where to extract the string from, so you should consider updating your JSON Output.
Related
The date receiving from server is not fixed in specific format then how can I detect which format am getting so that I can convert it into specific date format and display in the app according to the functionality.
Here are some examples that am receiving are:
2018-09-10T10:35:00.377Z
2018-09-10T10:35:00.12Z
2018-09-10
Thanks in advance!
java.time
String[] exampleStrings = {
"2018-09-10T10:35:00.377Z",
"2018-09-10T10:35:00.12Z",
"2018-09-10"
};
for (String example : exampleStrings) {
if (example.contains("T")) {
OffsetDateTime dateTime = OffsetDateTime.parse(example);
System.out.println("Date: " + dateTime.toLocalDate()
+ " Time: " + dateTime.toLocalTime()
+ " Offset: " + dateTime.getOffset());
} else {
LocalDate date = LocalDate.parse(example);
System.out.println("Date: " + date);
}
}
Your formats are allowed variants of ISO 8601. java.time, the modern Java date and time API, parses these formats without any explicit formatter. The first two example strings have date and time and the characteristic T to separate them, and an offset from UTC (Z means offset 0). The third has only a date. So test whether the string has the T in it and use the corresponding java.time class for the rest.
Output from the above snippet is:
Date: 2018-09-10 Time: 10:35:00.377 Offset: Z
Date: 2018-09-10 Time: 10:35:00.120 Offset: Z
Date: 2018-09-10
I don’t know how you will handle the two different types OffsetDateTime and LocalDate in the rest of your code. If you don’t need the time part, just the date, use dateTime.toLocalDate() to get a LocalDate and just pass this type on in all cases. Since you do need the time part, you may, depending on your situation and requirements, get away with the opposite conversion: in the date case you may get an OffsetDateTime from for example date.atStartOfDay().atOffset(ZoneOffset.UTC), but please do check whether this gives you an appropriate time.
I do agree with the now deleted answer by Khemraj, though, that your server ought to be able to deliver one consistent format or at least indicate which format it is giving you.
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
Wikipedia article: ISO 8601
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.
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.
Is there any alternative to TimeZone.getTimeZone() in Java, since getTimeZone() is synchronized, causing my program/application to scale down.
public static synchronized TimeZone getTimeZone(String ID) {
return getTimeZone(ID, true);
}
You don’t want to use TimeZone in 2018. Modern example:
ZoneId zone = ZoneId.of("America/Dawson_Creek");
The date and time classes from Java 1.0 and 1.1 — Date, Calendar, SimpleDateFormat and also TimeZone — are long outdated and were never well designed. java.time, the modern Java date and time API has been included with Java since Java 8 (out four years ago). It replaces them and is much nicer to work with.
If you thought you needed a TimeZone, for example for setting the time zone of a Calendar, this class too has been replaced (they all have, as I said). Instead use the modern ZonedDateTime:
ZonedDateTime dateTime = ZonedDateTime
.parse("2018-06-22T01:23:31.615464+11:00[Pacific/Guadalcanal]");
ZonedDateTime converted = dateTime.withZoneSameInstant(zone);
System.out.println("2018-06-22T01:23:31.615464 in Guadalcanal = " + converted);
Output:
2018-06-22T01:23:31.615464 in Guadalcanal =
2018-06-21T07:23:31.615464-07:00[America/Dawson_Creek]
It may of course occur that you need an old-fashioned TimeZone object for a legacy API that you either cannot change or don’t want to change just now. In that case use the conversion that Lino pointed out in another answer:
TimeZone oldfashionedTimeZone = TimeZone.getTimeZone(zone);
System.out.println(oldfashionedTimeZone);
sun.util.calendar.ZoneInfo[id="America/Dawson_Creek",offset=-25200000,dstSavings=0,useDaylight=false,transitions=58,lastRule=null]
If your problem is that the synchronization of TimeZone.getTimeZone(String) is slowing your program down, I am wondering how many TimeZone objects you are creating? With just 600 available time zone IDs (in my Java 10), I don’t think you need that many. I still clearly recommend ZoneId over TimeZone, but if the creation takes too long, caching them might be a better option?
Question: But what if I am using Java 6 or 7?
No big problem. java.time works nicely on Java 6 and 7 too. Only the conversions to the outdated classes are different, for example:
TimeZone oldfashionedTimeZone = DateTimeUtils.toTimeZone(zone);
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.
What about TimeZone.getTimeZone(ZoneId). Which is not synchronized:
// JDK 8 source
public static TimeZone getTimeZone(ZoneId zoneId) {
String tzid = zoneId.getId(); // throws an NPE if null
char c = tzid.charAt(0);
if (c == '+' || c == '-') {
tzid = "GMT" + tzid;
} else if (c == 'Z' && tzid.length() == 1) {
tzid = "UTC";
}
return getTimeZone(tzid, true);
}
See the following example:
TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("Europe"));
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
This question already has answers here:
Java: Check the date format of current string is according to required format or not [duplicate]
(8 answers)
How to sanity check a date in Java
(24 answers)
Closed 4 years ago.
I am trying to ensure that user entered a correct date format 10/08/2015 for example.
try{
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
d = sdf.parse(date.getText().toString());
}catch(ParseException ex){
Toast.makeText(MainActivity.this,
"Date format is wrong.", Toast.LENGTH_LONG).show();
return;
}
But it still parses most of the wrong inputs like 111/10/2013 or 11/109/2013 or some input containing characters.
Another question is how do i convert dd/mm/yyyy type date to NameofMonth day,year string ?
so 01/04/2018 will be converted to Apr 1,2018
DateTimeFormatter enteredFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
DateTimeFormatter usDateFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.US);
LocalDate d;
try {
d = LocalDate.parse(date.getText(), enteredFormatter);
System.out.println(d.format(usDateFormatter));
} catch (DateTimeParseException dtpe) {
Toast.makeText(MainActivity.this,
"Date format is wrong.", Toast.LENGTH_LONG).show();
return;
}
Getting the incorrect dates from your question this code will catch a java.time.format.DateTimeParseException: Text '111/10/2013' could not be parsed at index 2 or java.time.format.DateTimeParseException: Text '11/109/2013' could not be parsed at index 5 and therefore give the error message to the user. Given a correct date string like 11/10/2013 it prints like:
Oct 11, 2013
A detail that I haven’t tested on Android: As I understand, EditText.getText will return an Editable, which implements CharSequence. Since LocalDate.parse accepts a CharSequence, you can pass date.getText() with no need for .toString().
When formatting a date for an audience, the first thing you should consider is using one of Java’s built-in formatters for that audience’s locale. Your requested format agrees with the MEDIUM format for US locale. I took this to be no coincidence. So do take advantage.
At the same time I am taking advantage of java.time, the modern Java date and time API. SimpleDateFormat is notoriously troublesome and long outmoded. I avoid it. 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.