I have tried to convert string value to date object. I have tried some logic, but it didn't work. see my code :
public class Test {
public static void main(String[] args) {
try{
Test obj= new Test();
String date="2015-03-30T11:54:46.162430057Z";
Date dt=obj.getServerDate(date);
//System.out.println(dt);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public Date getServerDate(String str_date)
{
if (str_date == null)
return null;
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
System.out.println("Given date:" + str_date);
Date pars_date = null;
try
{
pars_date = fmt.parse(str_date);
System.out.println("Parsed date:" + pars_date);
}
catch (Exception e)
{
e.printStackTrace();
}
return pars_date;
}
}
The above code give the following output:
Given date:2015-03-30T11:54:46.162430057Z
Parsed date:Wed Apr 01 09:01:56 IST 2015
In the output the Given date and Parsed date is mismatch, I couldn't find any mistake in my code. Please let me know if you find the solution...
Thanks in advance.
The problem is with matching the server format with your parsing format.
You specify .SSS to handle milliseconds, but in the default configuration the number of "S" does not matter, SimpleDateFormat will consume until the next delimiter. This means that it will parse the first fields, and in the end add 162430057 milliseconds (about 45 hours) which gets you to the (correct, but unwanted and unexpected) Wed Apr 01 09:01:56 IST 2015.
If you are using Java 8 I recommend instead looking at DateTimeFormatter which can handle nanoseconds or if pre Java 8 use Joda Time.
If you are running on JDK 1.3 (which was End-Of-Life 2006/2007 depending on vendor) and you are certain of the time format, then you could use:
fmt(text.substring(0, 23) + 'Z')
or possibly remove the + 'Z'and remove the 'Z' from the format.
Using Date you will lose the nano second precision in any case as Date only holds milliseconds.
Related
I have a small block of code which parses response generation time from the response itself and turns it into a date for future purposes. It goes like this:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date responseTime = sdf.parse(RStime);
And it almost works like a charm. To be precise, it works 99.9% of the time, with the exception of one case: When the millisecond part is 000 then the Server doesn't append the .000 milliseconds at all, hence we have a problem.
Now, according to SimpleDateFormat docs if parsing fails, the function returns null. However, I probably misinterpreted it as it just throws an exception.
I am very new to Java and try-catch mechanisms, so could anyone please provide an elegant good-practice solution for handling such cases?
Thanks!
java.time
String rsTime = "2018-04-09T10:47:16.999-02:00";
OffsetDateTime responseTime = OffsetDateTime.parse(rsTime);
System.out.println("Parsed date and time: " + responseTime);
Output from this snippet is:
Parsed date and time: 2018-04-09T10:47:16.999-02:00
It works just as well for the version with the 000 milliseconds omitted:
String rsTime = "2018-04-09T10:47:16-02:00";
Parsed date and time: 2018-04-09T10:47:16-02:00
The classes you used, SimpleDateFormat and Date, are poorly designed and long outdated (the former in particular notoriously troublesome). So it is not only in this particular case I recommend using java.time, the modern Java date and time API, instead. However, the strings from your server are in ISO 8601 format, and OffsetDateTime and the other classes of java.time parse this format as their default, that is, without any explicit formatter, which already makes the task remarkably easier. Furthermore, in the standard the fractional seconds are optional, which is why both the variants of the string are parsed without any problems. OffsetDateTime also prints ISO 8601 back from it’s toString method, which is why in both cases a string identical to the parsed one is printed.
Only in case you indispensably need an old-fashioned Date object for a legacy API that you cannot change just now, convert like this:
Instant responseInstant = responseTime.toInstant();
Date oldfashionedDateObject = Date.from(responseInstant);
System.out.println("Converted to old-fashioned Date: " + oldfashionedDateObject);
Output on my computer in Europe/Copenhagen time zone is:
Converted to old-fashioned Date: Mon Apr 09 14:47:16 CEST 2018
Link: Oracle tutorial: Date Time explaining how to use java.time.
According to the SimpleDateFormat doc that you mentioned the parse method:
public Date parse(String text, ParsePosition pos)
Throws:
NullPointerException - if text or pos is null.
So one option is to catch that exception and do what you need inside the catch, for example:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
try {
Date responseTime = sdf.parse(RStime, position);
} catch (NullPointerException e) {
e.printStackTrace();
//... Do extra stuff if needed
}
Or the inherited method from DateFormat:
public Date parse(String source)
Throws:
ParseException - if the beginning of the specified string cannot be
parsed.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
try {
Date responseTime = sdf.parse(RStime);
} catch (ParseException e) {
e.printStackTrace();
//... Do extra stuff if needed
}
Is it actually an exceptional situation? If it is not then you probably shouldn't use exceptions in that case. In my opinion it is normal that time can end with .000ms. In this case you can check if the string contains . (dot) and if not append .000 to the end.
if(!RStime.contains(".")){
RStime+=".000";
}
Edit: I've forgot about time zone in the time String. You probably need something a little bit more complicated for that. Something like this should do it:
if(!RStime.contains(".")){
String firstPart = RStime.substring(0, 21);
String secondPart = RStime.substring(21);
RStime = firstPart + ".000" + secondPart;
}
You can check for a dot and then use the first or second format:
String timeString = "2018-04-09T10:47:16.999-02:00";
//String timeString = "2018-04-09T10:47:16-02:00";
String format = timeString.contains(".") ? "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" : "yyyy-MM-dd'T'HH:mm:ssXXX";
Date responseTime = new SimpleDateFormat(format).parse(timeString);
System.out.println("responseTime: " + responseTime);
If you comment-out the first line and comment-in the second and run it again, it will both print out:
responseTime: Mon Apr 09 14:47:16 CEST 2018
By the way:
Java 7 (the version you use obviously) returns a java.text.ParseException: Unparseable date: "2018-04-09T10:47:16-02:00"
Optionals are supported since Java 8.
I am using NetBeans IDE 7.2.
I have two separate classes newDateTest.java and newDateMethod.java, I am currently using my method class to validate a date from a user input which I have used in my test class.
So far in my test class I have the following:
try
{
Prompt ="please enter a date in the format dd-mm-yyyy";
System.out.println(Prompt);
String inputDate = in.next();
isValid = newDateMethod.validDate(input, input, input);
if (isValid){
System.out.println("VALID DATE");
} else {
System.out.println("INVALID DATE");
}
} catch (ArrayIndexOutOfBoundsException oob) {
System.out.println(oob);
}
However I have no idea how to validate the date in my method class as I am fairly new to Java.
Can anyone come to a solution? The sort of thing I've been taught to use is Date Formatter but I'm not sure whether this is appropriate here? If so, I wouldn't know how to use it
Like this:
Date date = null;
String inputDate = "07-01-2013";
try {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
formatter.setLenient(false);
date = formatter.parse(inputDate);
} catch (ParseException e) {
e.printStackTrace();
}
Updated on 13-Jul-2021:
I heartily agree with Ole V.V.'s comment below. All Java and Kotlin developers should prefer the java.time package.
I'll add a more modern example when time permits.
Have a look at SimpleDateFormat.parse(...) and do remember to surround with try-catch.
The standard JDK class for that is SimpleDateFormat:
DateFormat fmt = new SimpleDateFormat("yourformathere");
// use fmt.parse() to check for validity
Alternatively, I'd recommend using Joda Time's DateTimeFormat.
Rather than relying on exceptions which tend to have a small performance overhead, you can also use the DateValidator from the Apache commons routines package like this:
if (DateValidator.getInstance().validate(inputDate, "dd-MM-yyyy") != null) {
// Date is valid
}
else {
// Date is invalid
}
Small disclaimer though, I haven't looked at the implementation of the validate method and I'm not sure if it uses for instance the SimpleDateFormat...
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It also gives you much preciser validation than the old SimpleDateFormat class used in some of the other answers.
String[] exampleInputStrings = { "07-01-2013", "07-01-017",
"07-01-2ooo", "32-01-2017", "7-1-2013", "07-01-2013 blabla" };
for (String inputDate : exampleInputStrings) {
try {
LocalDate date = LocalDate.parse(inputDate, DATE_FORMATTER);
System.out.println(inputDate + ": valid date: " + date );
} catch (DateTimeParseException dtpe) {
System.out.println(inputDate + ": invalid date: " + dtpe.getMessage());
}
}
Output from my example code is:
07-01-2013: valid date: 2013-01-07
07-01-017: invalid date: Text '07-01-017' could not be parsed at index 6
07-01-2ooo: invalid date: Text '07-01-2ooo' could not be parsed at index 6
32-01-2017: invalid date: Text '32-01-2017' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
7-1-2013: invalid date: Text '7-1-2013' could not be parsed at index 0
07-01-2013 blabla: invalid date: Text '07-01-2013 blabla' could not be parsed, unparsed text found at index 10
For a good validation you should probably add a range check. Use the isBefore and/or the isAfter method of LocalDate.
Also if you are going to do anything with the date more than validating it, you should keep the LocalDate from the parsing around in your program (not the string).
Link
Oracle tutorial: Date Time explaining how to use java.time.
You should use SimpleDateFormat.parse(String) method. if the passed date is of wrong format it throws an exception in which case you return false.
public boolean validateDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.parse(date);
return true;
}
catch(ParseException ex) {
return false;
}
}
One can use joda-time.
DateTimeFormat.forPattern(INPUTED_DATE_FORMAT);
//one can also use it with locale
DateTimeFormat.forPattern(USER_DATE_FORMAT).withLocale(locale);
fmt.parseDateTime(INPUTED_DATE);
If parseDateTime throw IllegalArgumentException then date is not valid.
I am using NetBeans IDE 7.2.
I have two separate classes newDateTest.java and newDateMethod.java, I am currently using my method class to validate a date from a user input which I have used in my test class.
So far in my test class I have the following:
try
{
Prompt ="please enter a date in the format dd-mm-yyyy";
System.out.println(Prompt);
String inputDate = in.next();
isValid = newDateMethod.validDate(input, input, input);
if (isValid){
System.out.println("VALID DATE");
} else {
System.out.println("INVALID DATE");
}
} catch (ArrayIndexOutOfBoundsException oob) {
System.out.println(oob);
}
However I have no idea how to validate the date in my method class as I am fairly new to Java.
Can anyone come to a solution? The sort of thing I've been taught to use is Date Formatter but I'm not sure whether this is appropriate here? If so, I wouldn't know how to use it
Like this:
Date date = null;
String inputDate = "07-01-2013";
try {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
formatter.setLenient(false);
date = formatter.parse(inputDate);
} catch (ParseException e) {
e.printStackTrace();
}
Updated on 13-Jul-2021:
I heartily agree with Ole V.V.'s comment below. All Java and Kotlin developers should prefer the java.time package.
I'll add a more modern example when time permits.
Have a look at SimpleDateFormat.parse(...) and do remember to surround with try-catch.
The standard JDK class for that is SimpleDateFormat:
DateFormat fmt = new SimpleDateFormat("yourformathere");
// use fmt.parse() to check for validity
Alternatively, I'd recommend using Joda Time's DateTimeFormat.
Rather than relying on exceptions which tend to have a small performance overhead, you can also use the DateValidator from the Apache commons routines package like this:
if (DateValidator.getInstance().validate(inputDate, "dd-MM-yyyy") != null) {
// Date is valid
}
else {
// Date is invalid
}
Small disclaimer though, I haven't looked at the implementation of the validate method and I'm not sure if it uses for instance the SimpleDateFormat...
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It also gives you much preciser validation than the old SimpleDateFormat class used in some of the other answers.
String[] exampleInputStrings = { "07-01-2013", "07-01-017",
"07-01-2ooo", "32-01-2017", "7-1-2013", "07-01-2013 blabla" };
for (String inputDate : exampleInputStrings) {
try {
LocalDate date = LocalDate.parse(inputDate, DATE_FORMATTER);
System.out.println(inputDate + ": valid date: " + date );
} catch (DateTimeParseException dtpe) {
System.out.println(inputDate + ": invalid date: " + dtpe.getMessage());
}
}
Output from my example code is:
07-01-2013: valid date: 2013-01-07
07-01-017: invalid date: Text '07-01-017' could not be parsed at index 6
07-01-2ooo: invalid date: Text '07-01-2ooo' could not be parsed at index 6
32-01-2017: invalid date: Text '32-01-2017' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
7-1-2013: invalid date: Text '7-1-2013' could not be parsed at index 0
07-01-2013 blabla: invalid date: Text '07-01-2013 blabla' could not be parsed, unparsed text found at index 10
For a good validation you should probably add a range check. Use the isBefore and/or the isAfter method of LocalDate.
Also if you are going to do anything with the date more than validating it, you should keep the LocalDate from the parsing around in your program (not the string).
Link
Oracle tutorial: Date Time explaining how to use java.time.
You should use SimpleDateFormat.parse(String) method. if the passed date is of wrong format it throws an exception in which case you return false.
public boolean validateDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.parse(date);
return true;
}
catch(ParseException ex) {
return false;
}
}
One can use joda-time.
DateTimeFormat.forPattern(INPUTED_DATE_FORMAT);
//one can also use it with locale
DateTimeFormat.forPattern(USER_DATE_FORMAT).withLocale(locale);
fmt.parseDateTime(INPUTED_DATE);
If parseDateTime throw IllegalArgumentException then date is not valid.
public static void stringToDate(String time, String time2) {
try {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss");
Date t1 = formatter.parse(time);
System.out.println("Users first date: " + t1);
} catch (ParseException e){
System.out.println("Exception :" + e);
}
}
So above, I pass in 2 string parameters which are in the format of something like '17:23:56' and want them both converted into proper time objects that i can then find the difference between the 2, possibly in miliseconds or whatevers available if anyone knows how that'd be great.
Problem i'm having so far is that the output is: "Users first date: Thu Jan 01 17:23:56 GMT 1970", even though I thought I specified it to only parse it in HH:mm:ss. Anyone got the solution, thanks.
You're printing the result of Date#toString() ( <-- click the link!) which is indeed in the given format. If you want to present it in HH:mm:ss you have to use the format() method on the obtained Date.
System.out.println(formatter.format(t1));
Don't worry about this. Just parse the other time string to Date as well, do a getTime() on both and finally do the math.
I'm trying to make my code as generic as possible. I'm trying to parse install time of a product installation. I will have two files in the product, one that has time stamp I need to parse and other file tells the language of the installation.
This is how I'm parsing the timestamp
public class ts {
public static void main (String[] args){
String installTime = "2009/11/26 \u4e0b\u5348 04:40:54";
//This timestamp I got from the first file. Those unicode charecters are some Chinese charecters...AM/PM I guess
//Locale = new Locale();//don't set the language yet
SimpleDateFormat df = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.DEFAULT,DateFormat.DEFAULT);
Date instTime = null;
try {
instTime = df.parse(installTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(instTime.toString());
}
}
The output I get is
Parsing Failed
java.text.ParseException: Unparseable date: "2009/11/26 \u4e0b\u5348 04:40:54"
at java.text.DateFormat.parse(Unknown Source)
at ts.main(ts.java:39)
Exception in thread "main" java.lang.NullPointerException
at ts.main(ts.java:45)
It throws exception and at the end when I print it, it shows some proper date... wrong though. I would really appreciate if you could clarify me on these doubts
How to parse timestamps that have unicode characters if this is not the proper way?
If parsing is failed, how could instTime able to hold some date, wrong though?
I know its some chinese,Korean time stamps so I set the locale to zh and ko as follows.. even then same error comes again
Locale = new Locale("ko");
Locale = new Locale("ja");
Locale = new Locale("zh");
How can I do the same thing in Perl? I can't use Date::Manip package; Is there any other way?
Your example datetime stamp is not conforming to CLDR, so we have to define a pattern manually.
use utf8;
use DateTime::Format::CLDR ();
my $cldr = DateTime::Format::CLDR->new(
locale => 'zh_CN',
pattern => 'yyyy/MM/dd a HH:mm:ss',
on_error => 'croak',
);
$cldr->parse_datetime('2009/11/26 下午 04:40:54'); # returns a DateTime object
Try this:
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public class ts {
public static void main(final String[] args) {
String installTime = "2009/11/26 \u4e0b\u5348 04:40:54";
Locale[] locales = DateFormat.getAvailableLocales();
for (Locale locale : locales) {
try {
Date instTime = DateFormat.getDateInstance(DateFormat.LONG, locale).parse(
installTime);
System.out.println("BINGO! Worked with " + locale);
System.out.println(instTime);
} catch (Exception ex) {
}
}
}
}
Output:
BINGO! Worked with ja_JP
Thu Nov 26 00:00:00 GMT 2009
BINGO! Worked with ja
Thu Nov 26 00:00:00 GMT 2009
No, U+FFFF is not a valid character in any plane, so your string "installTime" contains undefined garbage.
Edit: furthermore, the code you posted is not the code you're running, since the code you posted (properly) results in
java.text.ParseException: Unparseable date: "2009/11/26 ~K~M~H 04:40:54"