how to solve the error when convert string date to integer? - java

I would like to convert my string date to int but I get an error, example of my date 'dim. janv. 23 24:00:00 +0000 2011`
This is part of my code :
String created_at = (String) jsonObject.get("created_at");
System.out.println("la date de création de tweet est: " + created_at);
DateFormat df = new SimpleDateFormat(" ddd. MMMM. EE HH:mm:ss z yyyy");
String s= df.format(created_at);
int out=Integer.valueOf(s);
System.out.println("new date " +out);
And the output is:
java.lang.IllegalArgumentException: Cannot format given Object as a Date.

Well, you already have the date in String format and that's what the format method does. I am assuming what you want to do here is to parse the date (into Date object) and not format.
Also, it looks like the date is in French locale, so you need to use appropriate locale along with SimpleDateFormat and use parse method, e.g.:
DateFormat df = new SimpleDateFormat("EEE MMMM dd HH:mm:ss z yyyy", Locale.FRANCE);
Date date = df.parse("dim. janv. 23 24:00:00 +0000 2011");
System.out.println(date);
This would give you the Date object. If you want to format it differently, you can call format method with different format.
Update
Also, it looks like you are calling overloaded version of format method (by passing in a String and not a Date object. This evantually calls format method of TextFormat class (javadoc here) and that's why you get that Exception.

I am aware that there is an accepted answer already. I am posting this to inspire you and anyone else to drop the outdated classes DateFormat and SimpleDateFormat. These days we have so much better in the modern DateTimeFormatter and friends, these classes tend to be much more programmer friendly. So use these if you can — which you can.
System.out.println("la date de création de tweet est: " + created_at);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss xx uuuu",
Locale.FRENCH);
OffsetDateTime dateTime = OffsetDateTime.parse(created_at, dtf);
This prints:
la date de création de tweet est: dim. janv. 23 24:00:00 +0000 2011
2011-01-24T00:00Z
In French the dots are part of the abbreviations for day of week and month, so they should not be explicit in the format pattern string. Also be aware that you don’t have a leading space in there (unless your date-time string has one too). The result is correct since midnight at 24 hours on 23th of January is the same as 0 hours in the 24th.
The other string from the comment, "Tue Feb 08 12:30:27 +0000 2011", is in the same format, only in English. So you need not change the format pattern, only the locale:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss xx uuuu",
Locale.ENGLISH);
Now the result is:
la date de création de tweet est: Tue Feb 08 12:30:27 +0000 2011
2011-02-08T12:30:27Z
I didn’t understand the part about converting to integer. I noticed you tried Integer.valueOf(s) in the code in the question, which will only work if you format the date-time into a string of digits first. For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd");
String s = dateTime.format(formatter);
int out = Integer.parseInt(s);
System.out.println("new date " + out);
This prints
new date 20110124
But I probably guessed incorrectly at what you are aiming at. I shall be happy to edit if you explain your requirement better. I used parseInt() en lieu of valueOf(), the result is the same, I just avoid the automatic conversion from Integer to int.
Edit: What if the date of creation of tweet is for example "dim. janv. 23 24:00:10 +0000 2011"? That is, 10 seconds past midnight. Then we get Invalid value for HourOfDay (valid values 0 - 23): 24.
While Java apparently accepts 24:00:00 as a time, it thinks that times after midnight should written as for example 0:00:10 on the following day. However, we can easily relax that requirement:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss xx uuuu",
Locale.FRENCH)
.withResolverStyle(ResolverStyle.LENIENT);
Date time formatters come with three resolver styles, strict, smart (the default) and lenient. Using the last one we get
2011-01-24T00:00:10Z
Again, as expected, 24:00:10 on 23th of January equals 0:00:10 on the 24th.

Related

Java Date Time conversion to given timezone

I have a DateTime in the format of Tue, 30 Apr 2019 16:00:00 +0800 which is RFC 2822 formatted date
I need to convert this to the given timezone in the DateTime which is +0800
So if i summarized,
DateGiven = Tue, 30 Apr 2019 16:00:00 +0800
DateWanted = 01-05-2019 00:00:00
How can i achieve this in Java?
I have tried the below code but it gives 08 hours lesser than the current time which is
30-04-2019 08:00:00
Code i tried
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date startDate = format.parse(programmeDetails.get("startdate").toString());
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
Date dttt= dateFormatLocal.parse( dateFormatGmt.format(startDate) );
You are on right approach but just use java-8 date time API module, first create DateTimeFormatter with the input format representation
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z");
And then use OffsetDateTime to parse string with offset
OffsetDateTime dateTime = OffsetDateTime.parse("Tue, 30 Apr 2019 16:00:00 +0800",formatter);
And the call the toLocalDateTime() method to get the local time
LocalDateTime localDateTime = dateTime.toLocalDateTime(); //2019-04-30T16:00
If you want the output in particular format again you can use DateTimeFormatter
localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) //2019-04-30T16:00:00
Note : As #Ole V.V pointed in comment, after parsing the input string into util.Date you are getting the UTC time
The class Date represents a specific instant in time, with millisecond precision.
So now if you convert the parsed date time into UTC you get 2019-04-30T08:00Z without offset, so you can use withOffsetSameInstant to convert it into any particular timezone
dateTime.withOffsetSameInstant(ZoneOffset.UTC)
You misunderstood. According to RFC 2822 +0800 means that an offset of 8 hours 0 minutes has already been applied to the time compared to UTC. So the output you got was the correct GMT time.
java.time
I recommend you skip the old and outdated classes SimpleDateFOrmat and Date. It’s much nicer to work with java.time, the modern Java date and time API. Furthermore it has the RFC format built in, so we don’t need to write our own formatter.
OffsetDateTime parsedDateTime = OffsetDateTime
.parse("Tue, 30 Apr 2019 16:00:00 +0800",
DateTimeFormatter.RFC_1123_DATE_TIME);
ZonedDateTime dateTimeInSingapore
= parsedDateTime.atZoneSameInstant(ZoneId.of("Asia/Singapore"));
System.out.println("In Singapore: " + dateTimeInSingapore);
OffsetDateTime dateTimeInGmt
= parsedDateTime.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("In GMT: " + dateTimeInGmt);
Output:
In Singapore: 2019-04-30T16:00+08:00[Asia/Singapore]
In GMT: 2019-04-30T08:00Z
The built-in formatter is named RFC_1123_DATE_TIME because the same format is used in multiple Requests for Comments (RFCs).
Links
RFC 2822 Internet Message Format
Oracle tutorial: Date Time explaining how to use java.time.
with the help of #ole v.v's explanation i have separated the datetime value for two
1. time
2. timezone
then i used this coding to extract the datetime which is related to the given timezone
//convert datetime to give timezone
private static String DateTimeConverter (String timeVal, String timeZone)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(timeZone));
String result =null;
try {
result = offsetDateFormat2.format(format.parse(timeVal));
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}

Java8 time library does not interpret BST timezone correctly

I am in the process of migrating my code to use the java.time package but I found that DateTimeFormatter does not interpret the time zone "BST" (British Summer Time) correctly.
Instead of making it UTC+0100, it converted it to Pacific/Bougainville timezone.
Does anybody know how I can fix this without going back to the old SimpleDateFormat, or use an explicit timezone? My code needs to run in multiple regions in the world.
This timestamp format is obtained by querying another system so I won't be able to change it. It seems SimpleDateFormat can recognize the timezone properly. My test code is below:
String sTime = "Fri Jun 07 14:07:07 BST 2019";
DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE MMM dd kk:mm:ss z yyyy");
ZonedDateTime zd = ZonedDateTime.parse(sTime, FORMATTER);
System.out.println("The time zone: " + zd.getZone());
FileTime ftReturn = FileTime.from(zd.toEpochSecond(), TimeUnit.SECONDS);
System.out.println("File time is: " + ftReturn);
DateFormat df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
Date dtDD = df.parse(sTime);
Calendar calendar = Calendar.getInstance();
calendar.setTime(dtDD);
FileTime ftReturn1 = FileTime.fromMillis(calendar.getTimeInMillis());
System.out.println("File time1 is: " + ftReturn1);
Test result:
The time zone: Pacific/Bougainville
File time is: 2019-06-07T03:07:07Z
File time1 is: 2019-06-07T13:07:07Z
According to https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html#SHORT_IDS:
BST - Asia/Dhaka
So I guess you should not use that abbreviation.
EDIT: Just found this question, which answers it.
So don't use Bangladesh Standard Time ;) Instead use ZoneId.of("Europe/London")
First, you’re trying to solve a task that cannot be solved. Three letter time zone abbreviations are ambiguous, I think more often than not. So if you solve the issue for Europe/London, you will have it again when you meet EST, IST, CST, CDT, PST, WST, and so on and so forth. Or when you meet a string where BST was intended to mean Brazil Summer Time, Bangladesh Standard Time or Bougainville Standard Time. Still more interpretations exist. Instead get an unambiguous string like one with a UTC offset rather than a time zone abbreviation, best a string in ISO 8601 format like 2019-06-07T14:07:07+01:00.
But if you’re sure that BST will always mean British Summer Time in your world, the short-sighted solution may be to tell the DateTimeFormatter which time zone/s you prefer:
String sTime = "Fri Jun 07 14:07:07 BST 2019";
ZoneId preferredZone = ZoneId.of("Europe/London");
DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss ")
.appendZoneText(TextStyle.SHORT, Collections.singleton(preferredZone))
.appendPattern(" yyyy")
.toFormatter(Locale.ROOT);
ZonedDateTime zd = ZonedDateTime.parse(sTime, FORMATTER);
System.out.println("The time zone: " + zd.getZone());
FileTime ftReturn = FileTime.from(zd.toEpochSecond(), TimeUnit.SECONDS);
System.out.println("File time is: " + ftReturn);
Output is:
The time zone: Europe/London
File time is: 2019-06-07T13:07:07Z
Links
Time Zone Abbreviations – Worldwide List
Documentation of the two-arg DateTimeFormatterBuilder.appendZoneText
Wikipedia article: ISO 8601
BST is ambiguous, as are many such abbreviations for timezones.
This solution is not great, but if you absolutely have to give precedence to BST to mean British Summer Time then you could just check whether the string contains that zone, and if it does, remove the zone and apply it manually.
String s = "Fri Jun 07 14:07:07 BST 2019";
if (s.contains(" BST ")) { // Check could be improved
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd kk:mm:ss yyyy");
s = s.replace(" BST ", " ");
ZonedDateTime dateTime = LocalDateTime.parse(s, formatter).atZone(ZoneOffset.ofHours(1));
}
else {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd kk:mm:ss z yyyy");
// Normal parsing
}
In future, consider representing your dates (either on-disk, or across an API) as offset strings instead, for example +01:00

DateTimeFormatter could not be parsed using "HH:mm E d MMM YYYY" pattern

I am retrieving a date/time from an external data source, this is returned in the following format "14:30 Sat 05 May" with no year.
I've been trying to parse this to a LocalDateTime unsuccessfully. The data returned does not return a year as it is an assumption that we are always operating in the current year.
//date to parse
String time = "14:30 Sat 05 May";
//specify date format matching above string
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm E d MMM YYYY") ;
//we do not have a year returned but i can make the assumption we use the current year
LocalDateTime formatDateTime = LocalDateTime.parse(time, formatter).withYear(2018);
The above code throws the following exception
Exception in thread "main" java.time.format.DateTimeParseException: Text '14:30 Sat 05 May' could not be parsed at index 16
Any help appreciated.
Default year
Specify a default year in your DateTimeFormatter, using the DateTimeFormatterBuilder class by calling parseDefaulting and specifying the year-field with ChronoField.YEAR.
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("HH:mm E d MMM")
.parseDefaulting(ChronoField.YEAR, 2018) // <------
.toFormatter(Locale.ENGLISH);
With this formatter instead of yours:
LocalDateTime.parse( "14:30 Sat 05 May" , formatter )
…I get:
2018-05-05T14:30
See that code run live at IdeOne.com.
Points to note:
Your format pattern string needs to match the parsed string end-to-end. So when your date-time string doesn’t have a year in it, don’t include YYYY in your format pattern.
In any case don’t use uppercase YYYY here. It’s for week-based year and only useful with week numbers. If your string had had a year in it, you should have used uuuu or lowercase yyyy.
Make it a habit to give explicit locale to your formatter so you know it also works on other computers, and on yours when one day you play with its settings.
LocalDateTime.parse() expects a String that represents a valid date, which the year part.
You cannot set the year after invoking this method in this way :
LocalDateTime.parse(time, formatter).withYear(2018);
The year has to be set before because otherwise parse() throws DateTimeParseException.
As a workaround you may concatenate the current year in the input.
Some additional notes:
the pattern you use and the input date in textual format don't match exactly.
You don't specify a Locale for the parsing operation.
It means that it will work according to the local where the JVM is run.
To ensure that it works in any case, you should specify the Locale.
So you could try something like :
//date to parse
String time = "14:30 Sat 05 May";
time += " " + LocalDate.now().getYear();
//specify date format matching above string
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm EEE dd MMM yyyy", Locale.US) ;
//we do not have a year returned but i can make the assumption we use the current year
LocalDateTime formatDateTime = LocalDateTime.parse(time, formatter);

Java - unparseable date, need format to match "GMT-0400"

I have the following Java:
DateFormat formatter = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zZ (zzzz)", Locale.ENGLISH);
Calendar cal = Calendar.getInstance();
cal.set(2011, Calendar.APRIL, 1);
out.println(formatter.format(cal.getTime()));
out.println();
Date date;
try {
date = formatter
.parse("Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)");
} catch (ParseException e) {
out.println("Failed to parse date: " + e.getMessage());
e.printStackTrace(out);
}
This is in a servlet, and the Calendar-constructed date comes out as:
Fri Apr 01 2011 16:42:24 EDT-0400 (Eastern Daylight Time)
This looks like the same format as the date string I'm trying to parse, except for EDT-0400 versus the desired GMT-0400. The code fails when trying to parse the date string:
java.text.ParseException: Unparseable date: "Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)"
How can I parse such a string? This is coming from a JavaScript date in a Sencha Touch 1.1.1 model, stored in WebSQL local storage.
For some reason GMT-0400 isnt' working, and UTC-0400 is working. You can replace GMT with UTC.
Note that this part will be completely ignored - the timezone will be resolved from what's found in the brackets (at least on my machine, JDK 6)
I debugged SimpleDateFormat and it seems that it will only parse GMT-04:00 but not GMT-0400.
It will accept UTC-0400, however it will throw away the hours/minutes modifier and will incorrectly parse it as UTC. (This happens with any other timezone designation, except for GMT)
It will also parse -0400 correctly, so the most robust solution is probably to simply remove GMT from your date string.
The upshot of the story is that SimpleDateFormat is anything but simple.
Update: Another lesson is that I could've saved a lot of time by passing a ParsePosition object to the parse() method:
DateFormat formatter = new SimpleDateFormat(
"EEE MMM dd yyyy HH:mm:ss zzzz", Locale.ENGLISH);
Date date;
ParsePosition pos = new ParsePosition( 0 );
date = formatter
.parse("Fri Apr 01 2011 00:00:00 UTC-0400", pos);
System.out.println( pos.getIndex() );
Will print out 28, indicating that the parsing ended at character index 28, just after UTC.

How to parse a date? [duplicate]

This question already has answers here:
Java string to date conversion
(17 answers)
Closed 6 years ago.
I am trying to parse this date with SimpleDateFormat and it is not working:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Formaterclass {
public static void main(String[] args) throws ParseException{
String strDate = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date dateStr = formatter.parse(strDate);
String formattedDate = formatter.format(dateStr);
System.out.println("yyyy-MM-dd date is ==>"+formattedDate);
Date date1 = formatter.parse(formattedDate);
formatter = new SimpleDateFormat("dd-MMM-yyyy");
formattedDate = formatter.format(date1);
System.out.println("dd-MMM-yyyy date is ==>"+formattedDate);
}
}
If I try this code with strDate="2008-10-14", I have a positive answer. What's the problem? How can I parse this format?
PS. I got this date from a jDatePicker and there is no instruction on how modify the date format I get when the user chooses a date.
You cannot expect to parse a date with a SimpleDateFormat that is set up with a different format.
To parse your "Thu Jun 18 20:56:02 EDT 2009" date string you need a SimpleDateFormat like this (roughly):
SimpleDateFormat parser=new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Use this to parse the string into a Date, and then your other SimpleDateFormat to turn that Date into the format you want.
String input = "Thu Jun 18 20:56:02 EDT 2009";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date = parser.parse(input);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = formatter.format(date);
...
JavaDoc: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
The problem is that you have a date formatted like this:
Thu Jun 18 20:56:02 EDT 2009
But are using a SimpleDateFormat that is:
yyyy-MM-dd
The two formats don't agree. You need to construct a SimpleDateFormat that matches the layout of the string you're trying to parse into a Date. Lining things up to make it easy to see, you want a SimpleDateFormat like this:
EEE MMM dd HH:mm:ss zzz yyyy
Thu Jun 18 20:56:02 EDT 2009
Check the JavaDoc page I linked to and see how the characters are used.
We now have a more modern way to do this work.
java.time
The java.time framework is bundled with Java 8 and later. See Tutorial. These new classes are inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. They are a vast improvement over the troublesome old classes, java.util.Date/.Calendar et al.
Note that the 3-4 letter codes like EDT are neither standardized nor unique. Avoid them whenever possible. Learn to use ISO 8601 standard formats instead. The java.time framework may take a stab at translating, but many of the commonly used codes have duplicate values.
By the way, note how java.time by default generates strings using the ISO 8601 formats but extended by appending the name of the time zone in brackets.
String input = "Thu Jun 18 20:56:02 EDT 2009";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM d HH:mm:ss zzz yyyy" , Locale.ENGLISH );
ZonedDateTime zdt = formatter.parse ( input , ZonedDateTime :: from );
Dump to console.
System.out.println ( "zdt : " + zdt );
When run.
zdt : 2009-06-18T20:56:02-04:00[America/New_York]
Adjust Time Zone
For fun let's adjust to the India time zone.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
zdtKolkata : 2009-06-19T06:26:02+05:30[Asia/Kolkata]
Convert to j.u.Date
If you really need a java.util.Date object for use with classes not yet updated to the java.time types, convert. Note that you are losing the assigned time zone, but have the same moment automatically adjusted to UTC.
java.util.Date date = java.util.Date.from( zdt.toInstant() );
How about getSelectedDate? Anyway, specifically on your code question, the problem is with this line:
new SimpleDateFormat("yyyy-MM-dd");
The string that goes in the constructor has to match the format of the date. The documentation for how to do that is here. Looks like you need something close to "EEE MMM d HH:mm:ss zzz yyyy"
In response to:
"How to convert Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México)) to dd-MM-yy in Java?", it was marked how duplicate
Try this:
With java.util.Date, java.text.SimpleDateFormat, it's a simple solution.
public static void main(String[] args) throws ParseException {
String fecha = "Tue Sep 13 2016 00:00:00 GMT-0500 (Hora de verano central (México))";
Date f = new Date(fecha);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("-5GMT"));
fecha = sdf.format(f);
System.out.println(fecha);
}

Categories