IllegalFormatConversionException d != java.lang.Integer when trying to printf date? - java

public void display() {
System.out.printf("%-10d%-12s%-12s%10.2f%8d%12.2f%1$td.%1$tm.%1$ty %n\n",
this.getID(),
this.getFirstName(),
this.getLastName(),
this.getState(),
this.getNo(),
this.getAmt(),
this.getDate());
}
Is my method for printing out some of my info. this.getDate returns date as a Date (java.util.Date) type.
I had an example given to me as System.out.printf("%1$td.%1$tm.%1$ty %n", date); to print out the data in a dd.mm.yyyy format. I tried to place that into my code, but by the looks of things I made a formatting mistake?
I've been trying a few printing methods now but find it confusing how it would work on its own but then I have issues when I try to place it into a larger printf statement.

The issue is that the number before the $-sign indicates the absolute index (starting with 1! 😉) of the Object. You intended to point at the Date (Index 7) but pointed at the first element instead, which happend to be an Integer. You'll want to use "%-10d%-12s%-12s%10.2f%8d%12.2f%7$td.%7$tm.%7$ty %n\n" for formatting.

First of all Date formatting is a complex issue and is already dealt with for you. So you trying to come up your own formatter (such as "%-10d%-12s%-12s%10.2f%8d%12.2f%td.%toString() of class Date. If you need better formatting than look at method DateFormat.format(Date date). However, note that if you use Java 8 or higher than the class java.util.Date shouldn't be used. Look at java.time package. Use ZonedDateTime or any of its "brothers" instead of Date and use DateTimeFormatter to format it to string

Related

XPages ODA issue with getting a date value from a field in Java

I'm using ODA (which is wonderful) in my Java code but I'm having trouble with getting a date value from a field.
If I use:
DateTime lastApprDt = doc.getItemValue("LastApproved", Date.class);
then the parser objects and suggests "change type of lastApprDt to Date"
If I change the code to:
Date lastApprDt = doc.getItemValue("LastApproved", Date.class);
then the parser is happy but when I run the code I get an error:
[ODA::WARNING] Auto-boxing requested a com.ibm.security.util.calendar.BaseCalendar$Date but is returning a org.openntf.domino.impl.DateTime in item LastApproved for document id 992
I'm confused! If doc.getItemValue("LastApproved", Date.class) returns a Date type then why do I get the error?
Make sure that the lastApprDt Date is of type java.util.Date (and not of type com.ibm.security.util.calendar.BaseCalendar.Date).
The first is failing because it's trying to pass a Date object (the output from getItemValue()) into a DateTime object (lastApprDate).
I'm not quite sure why it's choosing to retrieve it as a com.ibm.security.util.calendar.BaseCalendar.Date, I can't see any reference to that class in the ODA code. It's worth checking the import statements in your code to make sure it's not chosen com.ibm.security.util.calendar.BaseCalendar.Date as the relevant Date class it thinks you want to use. I suspect it may have done. If so, change the import statement to use java.util.Date.
The code for autoboxing Dates looks for specific classes and how to convert them. java.util.Date is the most obvious one it's expecting. I recently added java.sql.Date, I believe for the last base 9.0.1 and first FP8 versions. java.util.Calendar is the other one supported. New Java 8 Date classes like LocalDateTime may seem good candidates because they have better timezone handling, but it's not easy to convert the DateTime timezone to a Java timezone and the timezone in a DateTime is readonly, so it wouldn't work for autoboxing back at the moment.
You shouldn't need to pass the full class name as the second parameter, I've got code running that just passes Date.class. That's what makes me suspect that the parser suggestion has guessed at the wrong class you wanted and imported com.ibm.security.util.calendar.BaseCalendar.Date.
If you are sure that the field contains a date value you should be able to get the java.util.Date with
Date lastApprDt = doc.getItemValue("LastApproved").get(0).toJavaDate();

Migrating from Joda time to Java 8 DateTime

I could not find an alternative toDateTimeAtStartOfTheDay. For example
DateTime.now().toLocalDate().toDateTimeAtStartOfDay().plusHours(10)
how would I write above code in Java 8's DateTime library?
Closest I came to ZonedDateTime.now().toLocalDate().atStartOfDay() which just prints 2015-07-21T00:00.
I want something like 2015-07-21T00:00:00.000-04:00
If you need the time as a formatted String and you always like to get 10 o'clock of today, then don't bother calculating that time manually and write it into a format pattern:
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T10:00:00.000'XXX");
The meaning of each letter can be found here: JavaDoc of DateTimeFormatter. 'T10:00:00.000' is a fixed string and won't be parsed, just "added" to the returned String.
You can get the formatted time like this:
ZonedDateTime.now().format(format);
The output would be:
2015-07-21T10:00:00.000-04:00
You can use:
LocalDate.now().atStartOfDay().atZone(ZoneId.systemDefault());

Java : Custom Timestamp Format : verify format to microsec precision

My Objective is
to create a java class that can handle the below two requirements
(A) 1. Verify if the format of a timestamp matches with expected format.
CCYY-MM-DD'T'hh:mm:ss'.0000000000+'uh:um"
Ex: the expected format is not static.
It may be either of these
"2013-09-10T18:30:20.123456+10:00" or
"2013-09-10T18:30:20.123+10:00".
I am not bothered about the
precision and value. Only the format matters.
(B) 2. Verify if the timestamp is in a certain range.
Ex: Verify if the timestamp is in
between "2013-09-10 18:27" and "2013-09-10 18:33". (verification is only upto minute level precision) (may be a delta of + or - 2min)
As suggested by one of the member, I have edited the post to target at
One specific question.
The QUESTION :
How to validate the custom timestamp upto microsec precision using JAVA class ?
The two arguments for this class will be
1) Expected FORMAT as a String
2) timestamp value as a String
Based on analysis from various search results, below is my understanding :
Java (by default) does not parse/format Timestamp at microsecond level( I used SimpleDateFormat)
If 6 digits are given in milliseconds place, it will re-calculate the value into seconds and the dateformat will be updated and the new dateformat will have 3 digits in milliseconds precision.
I have also seen a thread which suggests to use java.sql.Timestamp.
Tried this approach but not working.
I was not able to convert my strTimestamp 2013-09-10T18:30:20.123456+10:00 into Timestamp object.
Timestamp ts = Timestamp.valueOf(strTimestamp);
java.lang.IllegalArgumentException:
Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
I was not able convert my input format into Timestamp object.
I have a workaround to validate using regular expression :
2013-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9]).[0-9][0-9][0-9][0-9][0-9][0-9]\+10:00
The problem with this reg ex is that, my expected timestamp format is not static. So i have to use a regex for every pattern.
So I am trying to figure out if there is any robust solution in java, which can be self sufficient even if the expected format changes.
java.time in Java 8
JSR 310 defined a new java.time package in Java 8. Its date-time class resolves to nanoseconds. That gives you 9 digits after the decimal point.
The java.time package is inspired by Joda-Time but entirely re-architected. Concepts are similar.
Like Joda-Time, the java.time package uses ISO 8601 formats as its defaults for parsing and formatting. So you can input or output strings such as 2013-09-10T18:30:20.123456789+10:00.
An early release of Java 8 is available now. Official release should be this month.
A project to backport this package to earlier versions of Java was underway. I do not know of its current status or success. The backport project is independent of Oracle and the OpenJDK project.
Milliseconds
The old bundled classes, java.util.Date & .Calendar, use a precision of milliseconds.
Ditto for the excellent Joda-Time library, milliseconds precision.
So not enough digits in the fractional seconds to meet your needs.
A java.sql.Timestamp is not going to help you, because that is a java.util.Date.
The code is fairly simple, if you use the right format String with SimpleDateFormat, which you let do the heavy lifting. Here's an entire working solution:
public static boolean isNear(String timestamp, int microPlaces, Date near, int minutes) {
if (!timestamp.matches(".*\\.\\d{" + microPlaces + "}\\D.*") {
return false;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ");
try {
Date date = sdf.parse(timestamp.replaceAll(":(?=\\d\\d$)", ""));
return Math.abs(date.getTime() - near.getTime()) <= minutes * 60000;
} catch (ParseException ignore) {
return false; // string was not of correct format
}
}
This may not be exactly what you had in mind - if not, you should be able to use it as a basis for what you want. The key points are:
The S format string means "microseconds", and it doesn't require all the digits - so your timestamp can have any number
Java 6 needs the colon removed from the timezone. Java 7 doesn't need this - use the X format string instead of Z
A failure to parse a date from the input throws a ParseException - do what you want with this event
I chose to make the API give central date for the range and a +/- minute value. You may need to pass two dates - up to you. Use Date.before() and Date.after() to compare if you do that.
Here's some test code testing your examples and a couple of edge cases:
public static void main(String[] args) throws Exception {
Date near = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm").parse("2013-09-10T18:32");
System.out.println(isNear("2013-09-10T18:30:20.123456+10:00", near, 2));
System.out.println(isNear("2013-09-10T18:30:20.123+10:00", near, 2));
System.out.println(isNear("2013-09-10T18:10:20.123+10:00", near, 1));
System.out.println(isNear("XXXX-09-10T18:10:20.123+10:00", near, 1));
}
Output:
true
true
false
false
Really I`m also trying to find answer to this problem. As I have no ability to add comment to the Bohemian answer. I want to mention that 'S' pattern in SimpleDateFormat is used not for microseconds but for milliseconds. It means that for pattern "yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ" provided microsecond digits in string would be parsed as milliseconds.
So the first three digits would be passed as XXX seconds and their value value would be added to date. So we can receive mistake about 16 minutes.

What is the difference between SimpleDateFormat and android.text.format.DateFormat?

From reading about them I understand that the android class is a utility class made for convenience only, and provide nothing that SimpleDateFormat doesn't provide. Is there any significance to the android class? Is it better practice to use it (if yes, why)? My goal is to display a Date object in an android app (obviously). Here it is:
private Date date;
public String getDateString(String formatStr){
return new SimpleDateFormat(formatStr).format(date);
}
would it be better to use android.text.format.DateFormat like this:
public String getDateString(String formatStr){
return android.text.format.DateFormat.format(formatStr, date);
}
or perhaps none of the two, but a different way would be best? thanks in advance.
Copying my answer from https://stackoverflow.com/a/27116266/642160 :
As far as I can tell, android.text.format.DateFormat has some of the functionality from java.text.DateFormat, some of the functionality from java.text.SimpleDateFormat, and some extra functionality of its own.
Most notably:
The java SimpleDateFormat allows construction of arbitrary non-localized formats.
The java DateFormat allows construction of three localized formats each for dates and times, via its factory methods.
The android DateFormat allows most of the above (arbitrary formats and a smaller number of localized formats), but also provides getBestDateTimePattern which picks a locale-appropriate format string that contains the elements specified with locale-appropriate ordering and punctuation.
So, if you need a localized date/time format other than the three provided by java's DateFormat class, the android DateFormat class is the solution.
Less importantly, but an additional convenience: the android DateFormat methods can take a Calendar or long milliseconds directly, instead of requiring a Date object. I always prefer working with Calendar or long over Date. Also, it properly respects the timezone of the Calendar object -- whereas getting a Date from a Calendar and passing that along to the formatter loses the timezone information. (Nothing you can't get around via java DateFormat's setCalendar method, but it's nice to not have to.)
Finally, and least importantly, some of the methods of the Android DateFormat don't actually construct a formatter, you just construct a format string. All of this class's methods are static. The methods do that construct a DateFormat actually construct a java DateFormat!
I believe the answer lies here:
This class' factory methods return appropriately-localized DateFormat
instances, suitable for both formatting and parsing dates.
I don't think the SimpleDateFormat provide appropriately-localized formats.

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