Milliseconds not appearing in DateFormat.format output - java

I want to have a date-time string in the "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format.
I wrote the following code snippet:
Date date=Calendar.getInstance().getTime();
String currentDateTimeString = (String) android.text.format.DateFormat.
format("yyyy-MM-dd'T'HH:mm:ss.SSSZ",Calendar.getInstance().getTime());
but I get strings like
"2019-11-08T13:39:33.SSSZ"
also when the format is "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" (with 'Z' escaped).
Patterns are found at https://developer.android.com/reference/java/text/SimpleDateFormat.html#examples
Why milliseconds do not appear?

I know little about Android development, but a quick search in the documentation may give you the answer:
https://developer.android.com/reference/android/text/format/DateFormat
The format methods in this class implement a subset of Unicode UTS #35 patterns. The subset currently supported by this class includes the following format characters: acdEHhLKkLMmsyz. Up to API level 17, only adEhkMmszy were supported. Note that this class incorrectly implements k as if it were H for backwards compatibility.
The Unicode UTS #35 says nothing about milliseconds:
https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
So it seems that formatting milliseconds is not supported.
I would rather use the Java standard classes LocalDateTime and DateTimeFormatter, which do support milliseconds.
https://developer.android.com/reference/java/time/format/DateTimeFormatter.html
[Edited]
After re-reading the question, I think the problem is that you're using DateFormat instead of SimpleDateFormat. The link you've provided does not correspond with the actual class you're using in your code.

Related

How Make operation on time

i have a string like this on my java code:
17:00
I want to make a subtraction using a constant integer
public static final int MAX_DUREE_TRAVAIL_JOUR = 10;
When i do this:
Integer.parseInt("17:00") - ConstantesIntervention.MAX_DUREE_TRAVAIL_JOUR
I have this error:
java.lang.NumberFormatException: For input string: "17:00"
Thx.
What are you expecting to happen? 17:00 is not a valid string representation of an integer.
You probably want to use a SimpleDateFormat to parse the string as a Date and do the time arithmetic on that.
Alternatively, take a look at the JodaTime library which provides much better handling of dates/times.
17:00 cant be to converted to an integer.
Because 17:00 is not a Correct integer.You should divide the string and use Integer.parse() then according to your business logic use those integers.
The answer by Ajai is correct.
Some advice: When working with dates and times, work with dates and times (not strings and integers). Meaning use date-time classes.
Use a good date-time library (not the mess that is java.util.Date/Calendar).
Use Joda-Time 2.3 now.
In the future, with Java 8, consider moving to JSR 310: Date and Time API which supplants the Date/Calendar classes and is inspired by Joda-Time.
P.S. Mercer, Joda-Time even knows how to speak français. See another answer of mine today for an example.

How to remove the SECONDS field from a DateFormat

I want to print a time without seconds in the default format for the locale.
So I get the formatter with getTimeInstance() or getTimeInstance(int style). But even when I use a SHORT style it will contain the seconds part of the time as well.
Is there any way (apart from creating my own format, which then would not be the locale default and manually maintained) I can grab the default and split off the seconds ?
Thanks
Roman
DateFormat.getTimeInstance(DateFormat.SHORT) works perfectly fine here: from 20:00:00 to 20:00 and from 8:00:00 PM to 8:00 PM.
EDIT: This is insufficient (as stated by the first comment below). I'm keeping this here for the sake of history and to keep others from responding in a similar fashion :)
Have you considered saving the current format as a string and manually removing the seconds using String's substring method?
In case someone is reading this and either uses Java 8 or later or is fine with a (good and futureproof) external library:
DateTimeFormatter noSeconds = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(Locale.ITALY);
LocalTime time = LocalTime.now(ZoneId.systemDefault());
System.out.println(time.format(noSeconds));
This just printed:
15.26
Please substitute your desired locale instead of Locale.ITALY. Use Locale.getDefault() for your JVM’s locale setting. I believe it prints without seconds in all locales.
In the code I have used a LocalTime object, but the same code works for many other date and time classes including LocalDateTime, OffsetDateTime, OffsetTime and ZonedDateTime.
To use DateTimeFormatter and any of the other classes mentioned on Android you need the ThreeTenABP. More details on how to in this question: How to use ThreeTenABP in Android Project. For any non-Android Java 6 or 7, use ThreeTen Backport.

Why does SimpleDateFormat parse incorrect date?

I have date in string format and I want to parse that into util date.
var date ="03/11/2013"
I am parsing this as :
new SimpleDateFormat("MM/dd/yyyy").parse(date)
But the strange thing is that, if I am passing "03-08-201309 hjhkjhk" or "03-88-2013" or 43-88-201378", it does not throw error , it parses it.
For this now, I have to write regex pattern for checking whetehr input of date is correct or not.
but why is it so ??
Code :
scala> val date="03/88/201309 hjhkjhk"
date: java.lang.String = 03/88/201309 hjhkjhk
scala> new SimpleDateFormat("MM/dd/yyyy").parse(date)
res5: java.util.Date = Mon May 27 00:00:00 IST 201309
You should use DateFormat.setLenient(false):
SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy");
df.setLenient(false);
df.parse("03/88/2013"); // Throws an exception
I'm not sure that will catch everything you want - I seem to remember that even with setLenient(false) it's more lenient than you might expect - but it should catch invalid month numbers for example.
I don't think it will catch trailing text, e.g. "03/01/2013 sjsjsj". You could potentially use the overload of parse which accepts a ParsePosition, then check the current parse index after parsing has completed:
ParsePosition position = new ParsePosition(0);
Date date = dateFormat.parse(text, position);
if (position.getIndex() != text.length()) {
// Throw an exception or whatever else you want to do
}
You should also look at the Joda Time API which may well allow for a stricter interpretation - and is a generally cleaner date/time API anyway.
Jon Skeet’s answer is correct and was a good answer when it was written in 2013.
However, the classes you use in your question, SimpleDateFormat and Date, are now long outdated, so if someone got a similar issue with them today, IMHO the best answer would be to change to using the modern Java date & time API.
I am sorry I cannot write Scala code, so you will have to live with Java. I am using
private static DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy");
The format pattern letters are the same as in your question, though the meaning is slightly different. DateTimeFormatter takes the number of pattern letters literally, as we shall see. Now we try:
System.out.println(LocalDate.parse(date, parseFormatter));
Results:
"03/11/2013" is parsed into 2013-03-11 as expected. I used the modern LocalDate class, a class that represents a date without time-of-day, exactly what we need here.
Passing "03/88/2013 hjhkjhk" gives a DateTimeParseException with the message Text '03/88/2013 hjhkjhk' could not be parsed, unparsed text found at index 10. Pretty precise, isn’t it? The modern API has methods to parse only part of a string if that is what we want, though.
"03/88/201309" gives Text '03/88/201309' could not be parsed at index 6. We asked for a 4 digit year and gave it 6 digits, which leads to the objection. Apparently it detects and reports this error before trying to interpret 88 as a day of month.
It does object to a day of month of 88 too, though: "03/88/2013" gives Text '03/88/2013' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 88. Again, please enjoy how informative the message is.
"03-08-2013" (with hyphens instead of slashes) gives Text '03-08-2013' could not be parsed at index 2, not very surprising. Index 2 is where the first hyphen is.
Jon Skeet explained that the outdated SimpleDateFormat can be lenient or non-lenient. This is true for DateTimeFormatter too, in fact it has 3 instead of 2 resolver styles, called ‘lenient’, ‘smart’ and ‘strict’. Since many programmers are not aware of this, though, I think they made a good choice of not making ‘lenient’ the default (‘smart’ is).
What if we wanted to make our formatter lenient?
private static DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy")
.withResolverStyle(ResolverStyle.LENIENT);
Now it also parses "03/88/2013", into 2013-05-27. I believe this is what the old class would also have done: counting 88 days from the beginning of March gives May 27. The other error messages are still the same. In other words it still objects to unparsed text, to a 6 digit year and to hyphens.
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (that’s ThreeTen for JSR-310, where the modern API was first defined).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and I think that there’s a wonderful explanation in this question: How to use ThreeTenABP in Android Project.

What is the correct pattern for parsing the timezone format with SimpleDateFormat

I want to define a pattern for the Java SimpleDaterFormat to parse existing strings.
The existing dates look like this: 2011-05-02T13:40:00+02:00.
I tried with different patterns, but I got ParseExceptions. The problem seems to be the timezone format.
Printing the pattern in Java:
yyyy-MM-dd'T'HH:mm:ssZ
2012-03-14T15:40:44+0100
yyyy-MM-dd'T'HH:mm:ssz
2012-03-14T15:41:58MEZ
But how can I get
???
2011-05-02T13:40:00+02:00
I'm using Java 6, not Java 7.
If you can use Java 7 or newer, you can use the XXX pattern to get the timezone to look like +02:00:
yyyy-MM-dd'T'HH:mm:ssXXX
Otherwise you might have to manipulate the date string to remove the colon from the timezone before parsing it.
I know it's a bit old question, but someone else might benefit from my hint.
You can use JodaTime. As library documentation stands:
Zone: 'Z' outputs offset without a colon, 'ZZ' outputs the offset with
a colon, 'ZZZ' or more outputs the zone id.
You can use it as well with java 6. You have more examples in this question

RFC822 Timezone Parsing in Java

I have a JS date that is being converted by Dojo into RFC822 format. The function call -
dojo.date.toRfc3339(jsDate), generates the following date - 2007-02-26T20:15:00+02:00.
I have an application that uses a Java date SimpleDateFormat to parse in the dates generated above. I am having problems parsing this date format due to the timezone. I have attempted to use
yyyy-mm-DD'T'hh:mm:ssZ
This fails as the 'Z' for timezone doesn't expect a ':' character. Does anyone know how I would specify a pattern to handle a RFC822 date with the ':'?
revision:
Thanks for correctly interpreting what I am trying to do :) I was meant to say the date is generating in RFC3339 and I needed RFC822. Looks like I will have to override the JavaScript. I was hoping that I wouldn't have to do that and could specify a date format pattern without having to modify any Java Code as the date format is simply injected into a Spring bean of an application.
Just for completeness, is there a way to specify in a date format expression to ignore characters in the sequence (without doing String manipulation/replacement)? In this case I'd be saying ignore any ':' or just ignore the timezone all together?
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
public static Date ParseRFC3339DateFormat(String p_date)
{
try{
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String dts = p_date.replaceAll("([\\+\\-]\\d\\d):(\\d\\d)","$1$2");
return formatter.parse(dts);
}catch (Exception e) {
return null;
}
}
}
This works
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-DD'T'hh:mm:ssZ");
format.parse("2007-02-26T20:15:00+02:00".replaceAll("([\\+\\-]\\d\\d):(\\d\\d)","$1$2"));
(Note I've taking the final colon out of the format after the 'Z' format specifier.)
RFC822 does not allow a colon to be in the time zone portion of date. It expects just the 4 digits. The name of that Dojo method indicates that it is using RFC3339. It seems that is practically the same format as ISO8601. It just so happens that Joda Time has ISODateTimeFormat which is ISO8601 compatible if you are able to use that library. The method dateTimeNoMillis() looks like a match with the Dojo format. It really is nicer than the standard Java date and time API. Otherwise highlycaffeinated's suggestion would be the way to go.
Updated in response to Jamen's update
Isn't there a way to have Dojo use a format that doesn't include the timezone? Then you can adjust the format on the Java side to match. I don't know much about Dojo and I haven't been able to find any documentation on the toRfc3339 function it provides.
In Java 8 you can use:
Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse( rfc822Time ) );
FYI: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#RFC_1123_DATE_TIME
I'd strip the ':' out of the timezone and use the format you have above.
Instead of using dojo.date.toRfc3339(jsDate) you could create your own function with a custom format string.
Something like the following would remove the colon and should be parsable by your java format.
function toRfc3339String(jsDate){
return dojo.date.locale.format(jsDate,{selector: 'date', datePattern:'yyyy-MM-dd\'T\'hh:mm:ssZ'});
}
You can do this generically without Java 7. I have asked 2 questions in StackOverflow on this, within 2012, so there is a solution that does not need any third party libraries.
Just check the implementation presented in the description of my latest question, which also points to the earlier one that discusses exactly this issue.

Categories