I am working on server and server is sending me date on GMT Local Date like Fri Jun 22 09:29:29 NPT 2018 on String format and I convert it into Date like below:
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",Locale.English);
Date newDate=simpleDateFormat.parse("Fri Jun 22 09:29:29 NPT 2018");
TimeAgo ta=new TimeAgo();
Log.d(TAG,""+ta.timeAgo(newDate));
What I need is take out the Time in Ago like 5 hours ago for that I use the one github project on which returns TimeAgo on passing date.
I have already look at this answer but didn't solve my problem.
Exception: Err java.text.ParseException: Unparseable date: "Fri Jun 22 09:29:29 NPT 2018" (at offset 20)
Err java.text.ParseException: Unparseable date: "Fri Jun 22 09:29:29 NPT 2018" (at offset 20)
NPT is not recognized as a time zone abbreviation
The parsing of your date-time string (apparently the output from Date.toString()) is the problem (not the subsequent use of TimeAgo, which you could have left out from the question to make it clearer). The unparseable part is at index 20, that is where it says NPT, which I take to mean Nepal Time. So SimpleDateFormat on your Android device or emulator doesn’t recognize NPT as a time zone abbreviation.
Time zone abbreviations come as part of the locale data. I am not an Android developer and don’t know from where Android gets its locale data. A fast web search mentioned ICU and CLDR. You can search more thoroughly and no doubt find information I didn’t find.
I am presenting three suggestions for you to try. I admit at once that the first two are unlikely to solve your problem, but I nevertheless find them worth trying. And I promise that the third will work if the first two don’t.
1. Use ThreeTenABP and java.time
I agree with the answer by notyou that the classes Date and SimpleDateFormat are outmoded and that it’s better to use java.time, the modern Java date and time API. Can you do that on Android prior to Android O? Yes, most of java.time has been backported. The Android edition of the backport is called ThreeTenABP. Use the links at the bottom. Then try:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
ZonedDateTime newDateTime
= ZonedDateTime.parse("Fri Jun 22 09:29:29 NPT 2018", formatter);
System.out.println(newDateTime);
Make sure you use the imports for the backport:
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeFormatter;
I have tested with the same backport, only not the Android edition. I got:
2018-06-22T09:29:29+05:45[Asia/Kathmandu]
I suspect that ThreeTenABP uses the same locale data, though, and if so, this doesn’t solve your problem.
2. Set the time zone on the formatter
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT)
.withZone(ZoneId.of("Asia/Kathmandu"));
If it works, I find it straightforward and clean. If you insist on using SimpleDateFormat, you can try a similar trick with it. I get the same output as above.
3. Handle NPT as literal text
This is a hack: require that the three letters NPT occur in the string without interpreting them as a time zone. This eliminates the need for the abbreviation to be recognized as a time zone, so will work.
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("EEE MMM dd HH:mm:ss 'NPT' yyyy", Locale.ROOT)
.withZone(ZoneId.of("Asia/Kathmandu"));
We also need to set the time zone since this is now the only place Java can get the time zone from.
But TimeAgo requires a Date
To obtain an old-fashioned Date object for TimeAgo, convert like this:
Date newDate = DateTimeUtils.toDate(newDateTime.toInstant());
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.
The Date class is predominantly deprecated, so I would suggest not to use that.
Perhaps consider using something like the ZonedDateTime class for your problem.
If you're just looking for 5 hours before the String sent over to you, you could use something like:
String time = "Fri Jun 22 09:29:29 NPT 2018";
DateTimeFormatter format = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz uuuu");
ZonedDateTime zdt = ZonedDateTime.parse(time, format);
System.out.println(zdt.minusHours(5));
Related
I am trying to parse the following kind of date: Dec 12 2001 11:59:59PM.
If the AM/PM wasn't next to the seconds, I would use the following pattern: MMM dd yyyy HH:mm:ss a.
However the AM/PM is ignored with the pattern MMM dd yyyy HH:mm:ssa (and is therefore always interpreted as AM).
I am trying to use a SimpleDateFormat. I tried to specify a locale to no avail.
Is this possible using a SimpleDateFormat or do I need to use an alternative method/external processing? The SimpleDateFormat particularly interests me due to its use in the pattern attribute of the #JsonFormat annotation.
Thanks.
I would like to use java.time API from Java8+ instead of the old Date :
String date = LocalDateTime.now().format(
DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm:ssa", Locale.ENGLISH)
);
or :
DateTimeFormatter format = DateTimeFormatter.ofPattern(
"MMM dd yyyy hh:mm:ssa", Locale.ENGLISH
);
String date = LocalDateTime.of(2001, Month.DECEMBER, 12, 11, 59, 59).format(format);
Outputs
Jun 14 2018 03:01:02PM
Dec 12 2001 11:59:59AM
with AM/PM you want 12 hours hh instead of 24 hours HH.
hh:mm:ss''a
As k/K/h/H influence a too, now everything might work with ssa.
If ssa is still problematic (seemingly a bug), try separating the letters by an empty literal string (single quotes).
The following works:
hh:mm:ssa
It may very well be possible with SimpleDateFormat, but you will probably prefer to use java.time, the modern Java date and time API:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("MMM dd uuuu hh:mm:ssa", Locale.ENGLISH);
String dateTimeString = "Dec 12 2001 11:59:59PM";
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);
Output:
2001-12-12T23:59:59
As others have said, your problem was not with the lack of a space between seconds and AM/PM marker, but with using uppercase HH for the hours. Uppercase HH is for hour of day from 00 through 23, where what you wanted was lowercase hh for hour within AM or PM from 01 through 12.
And as yet others have said, there are issues with using SimpleDateFormat and its friend Date:
Those classes are long outdated.
Those classes are poorly designed, and SimpleDateFormat in particular is renowned for being troublesome. Your experience is typical and certainly not unusual.
Getting a correct result from SimpleDateFormat requires that either the JVM time zone setting agrees with the time zone understood in the string, or you set the time zone of the SimpleDateFormat to the relevant time zone. The former is hard to guarantee since the time zone setting can be changed any time from another part of your program or from other programs running in the same JVM.
This also means that if you do require an instance of the outdated Date class (for example for a legacy API that you don’t want to change just now), you will need to decide on a time zone for the conversion. Then convert for example like this:
Instant inst = dateTime.atZone(ZoneId.of("America/Metlakatla")).toInstant();
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
I hesitate to show you the output because Date shows a quite surprising behaviour here.
Thu Dec 13 08:59:59 CET 2001
08:59? On December 13? The conversion has given you the correct point in time. When I print the Date, its toString method is invoked. This in turn uses my JVM’s time zone setting for producing the string, so the output is in a completely different time zone from the one where the conversion happened. So apparently when it’s 23:59 in Metlakatla, it’s already 08:59 the next day in Copenhagen (my time zone; CET in the output is for Central European Time). Had my JVM’s time zone setting been America/Metlakatla too, the output would have agreed more with the expected:
Wed Dec 12 23:59:59 AKST 2001
java.time is more helpful
What you asked SimpleDateFormat to do was to parse a time that had hour of day 11 and PM. This is really self contradictory since PM only begins at hour of day 12. So it would be reasonable to expect an exception from the request. A SimpleDateFormat with standard settings doesn’t give you that. It’s very typical for SimpleDateFOrmat to give you a wrong result and pretend all is well. However let’s for a moment try my modern code with your format pattern string of MMM dd yyyy HH:mm:ssa. Then we get:
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Dec 12 2001 11:59:59PM' could not be parsed: Conflict found:
Field AmPmOfDay 0 differs from AmPmOfDay 1 derived from 11:59:59
I don’t claim I understand exactly why it is worded like this, but it is mentioning a conflict in the AM/PM, which is exactly what we have.
PS
I hadn’t thought at first that I’d contribute an answer, but in the end I was provoked by on one hand bohemian’s comment that only Joop Eggen’s answer was correct and on the other hand a couple of comments by Basil Bourque claiming that you could not use the SimpleDateFormat that Joop Eggen was using. So I wanted to set things straight.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Java internally uses the builder pattern. This is slightly modified from the source code of DateTimeFormatter.RFC_1123_DATE_TIME:
I don't recommend using this over the alternative, DateTimeFormatter.ofPattern(), but it can prove more powerful in certain scenarios where you hit the limitations of ofPattern.
Map<Long, String> moy = new HashMap<>();
moy.put(1L, "Jan"); moy.put(2L, "Feb"); moy.put(3L, "Mar");
moy.put(4L, "Apr"); moy.put(5L, "May"); moy.put(6L, "Jun");
moy.put(7L, "Jul"); moy.put(8L, "Aug"); moy.put(9L, "Sep");
moy.put(10L, "Oct"); moy.put(11L, "Nov"); moy.put(12L, "Dec");
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendText(MONTH_OF_YEAR, moy)
.appendLiteral(' ')
.appendValue(DAY_OF_MONTH, 2)
.appendLiteral(' ')
.appendValue(YEAR, 4, 4, EXCEEDS_PAD)
.appendLiteral(' ')
.appendValue(HOUR_OF_AMPM, 1, 2, NOT_NEGATIVE)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 1, 2, NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 1, 2, NOT_NEGATIVE)
.optionalEnd()
.appendText(AMPM_OF_DAY)
.toFormatter();
System.out.println(format.parse("Jun 14 2018 2:51:22AM")); // {},ISO resolved to 2018-06-14T02:51:22
System.out.println(format.parse("Jun 14 2018 2:51:22PM")); // {},ISO resolved to 2018-06-14T14:51:22
Note
Unfortunately, the below code is inaccurate. AM/PM marker is never read. Depending on the local time, either AM or PM is assumed.
Original answer
Use the following format string "MMM dd yyyy HH:mm:ssaaa".
String str = "Jun 14 2018 13:53:19PM";
DateFormat df = new SimpleDateFormat("MMM dd yyyy HH:mm:ssaaa");
try {
Date date = df.parse(str);
System.out.print(df.format(date));
} catch (ParseException e) {
e.printStackTrace();
}
I am trying to convert a string such as
String dateString = "Mon Mar 30 13:51:35 UTC 2015";
in a Date Object.
I tried this:
DateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Date Object:"+sdf.parse(dateString));
But the output of the date object is
Mon Mar 30 15:51:35 CEST 2015
as you can see:
1) it forwards the string's time ahead to two hours
2) it changes UTC --> CEST
I tried many solutions, but nothing worked. What is the correct way to do this?
EDIT: my objective here is to have a Date object from that original String. That Date Object should have the same parameters as the date string. In this case, the original hours of day (13) is turned to 15, but the desired is for it to stay at 13. I need this because in my program I will need to compare two different date objects.
EDIT: JAVA 8 SOLUTION
Searching the more recent Java 8, I found a better and more elegant solution. Here is the code
String pattern = "EEE MMM dd HH:mm:ss SSS zzz yyyy";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.UK).withZone(ZoneId.of("UTC"));
final ZonedDateTime parsed = ZonedDateTime.parse(dateString, formatter);
Furthermore, to compare it with, for example, the current time:
ZonedDateTime now = ZonedDateTime.now();
int compared = parsed.compareTo(now);
System.out.println("NOW:"+now.toLocalDateTime()+" PARSED:"+parsed.toLocalDateTime()+" COMPARED:"+compared);
You are doing it correctly. The date is being parsed correctly. You are just printing the date into your local computer timezone. When you do toString() to a date, prints the date in your local machine timezone.
Mon Mar 30 15:51:35 CEST 2015 == Mon Mar 30 13:51:35 UTC 2015
CEST is UTC +2
A java.util.Date does not have a time zone, practically speaking. There is a time zone inside but it cannot be set nor gotten. One of many poor design decisions made in these old date-time classes.
The Date::toString method applies your JVM’s current default time zone when generating the output string. Done with good intentions, but not helpful as it creates the illusion your Date object is in that zone when in fact it is not.
java.time
You are using a troublesome old legacy class, now supplanted by the java.time framework built into Java 8 and later.
Convert from a Date to an Instant, a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = myJavaUtilDate.toInstant();
Call toString. The java.time classes use standard ISO 8601 formats when parsing/generating strings.
String output = instant.toString();
To create strings, convert from Instant to OffsetDateTime using the constant ZoneOffset.UTC. Then work with the java.time.format classes to generate the string.
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , ZoneOffset.UTC );
Search Stack Overflow for more info and examples. These issues have addressed hundreds of times already.
Instead of UTC, use GMT when getting the timezone.
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Source
You already have the Date object. If you want to print it in format you want, you can use DateFormat to format the Date object as well:
Date date = sdf.parse(dateString);
System.out.println("Date Object:"+sdf.format(date));
// Use the date object ...
I am trying to determine what java date format string to use for
"Fri Jun 05 00:00:00 PDT 2015"
Right now I am using
SimpleDateFormat format = new SimpleDateFormat("EEE MM dd HH:mm:ss zzzz yyyy");
But this yields
com.fasterxml.jackson.databind.JsonMappingException:
java.text.ParseException: Unparseable date: "Fri Jun 05 00:00:00 PDT 2015"
(through reference chain:....
You need one additional M for the month:
EEE MMM dd HH:mm:ss zzzz yyyy
This is mentioned in the Javadocs of SimpleDateFormat:
Month: If the number of pattern letters is 3 or more, the month is interpreted as text; otherwise, it is interpreted as a number.
Locale is as important as the pattern
Irrespective of the applicable pattern, it's important to use Locale as a date-time parsing/formatting type (e.g. the smart and vivid DateTimeFormatter of the modern API, or the notorious and error-prone SimpleDateFormat of the legacy API) is Locale-sensitive. Since your date-time string is in English, you should use Locale.ENGLISH.
Note that the legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.
Demo using modern date-time API:
For the abbreviated month name, you need to use MMM instead of MM.
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d H:m:s zzz u", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse("Fri Jun 05 00:00:00 PDT 2015", dtf);
System.out.println(zdt);
}
}
Output:
2015-06-05T00:00-07:00[America/Los_Angeles]
For whatsoever reason, if you need an instance of java.util.Date from this object of ZonedDateTime, you can do so as follows:
Date date = Date.from(zdt.toInstant());
Learn more about the the modern date-time API* from Trail: Date Time.
Note: Ask your publisher to send the timezone name in the format, Region/City as shown in the above output. The three-letter timezone name (e.g. PDT) is ambiguous and hence, error-prone.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
I got a date time format - "dd MMM yyyy", when trying to parse "6 Aug 2012", I get an java.text.ParseException Unparseable date.
Every thing looks fine, do you see the problem?
You need to mention the Locale as well...
Date date = new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH).parse("6 Aug 2012");
Use something like:
DateFormat sdf = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH);
Date date = sdf.parse("6 Aug 2012");
Use the split() function with the delimiter " "
String s = “6 Aug 2012”;
String[] arr = s.split(" ");
int day = Integer.parseInt(arr[0]);
String month = arr[1];
int year = Integer.parseInt(arr[2]);
This should work for you. You will need to provide a locale
Date date = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse("6 Aug 2012");
Or
Date date = new SimpleDateFormat("dd MMM yyyy", new Locale("EN")).parse("6 Aug 2012");
While the other answers are correct but outdated and since this question is still being visited, here is the modern answer.
java.time and ThreeTenABP
Use java.time, the modern Java date and time API, for your date work. This will work with your Android version/minSDK:
DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("d MMM uuuu", Locale.ENGLISH);
String str = "6 Aug 2012";
LocalDate date = LocalDate.parse(str, dateFormatter);
System.out.println(date);
Output:
2012-08-06
In the format pattern java.time uses just one d for either one or two digit day of month. For year you may use either of yyyy, uuuu, y and u. And as the others have said, specify locale. If Aug is English, then an English-speaking locale.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both 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) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern 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
Similar question to this one: Java - Unparseable date.
Oracle tutorial: Date Time explaining how to use java.time.
Question: uuuu versus yyyy in DateTimeFormatter formatting pattern codes in Java?
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 database field that contains a raw date field (stored as character data), such as
Friday, September 26, 2008 8:30 PM Eastern Daylight Time
I can parse this as a Date easily, with SimpleDateFormat
DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
Date scheduledDate = dbFormatter.parse(rawDate);
What I'd like to do is extract a TimeZone object from this string. The default TimeZone in the JVM that this application runs in is GMT, so I can't use .getTimezoneOffset() from the Date parsed above (because it will return the default TimeZone).
Besides tokenizing the raw string and finding the start position of the Timezone string (since I know the format will always be EEEE, MMMM dd, yyyy hh:mm aa zzzz) is there a way using the DateFormat/SimpleDateFormat/Date/Calendar API to extract a TimeZone object - which will have the same TimeZone as the String I've parsed apart with DateFormat.parse()?
One thing that bugs me about Date vs Calendar in the Java API is that Calendar is supposed to replace Date in all places... but then they decided, oh hey let's still use Date's in the DateFormat classes.
I found that the following:
DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time");
System.out.println(scheduledDate);
System.out.println(dbFormatter.format(scheduledDate));
TimeZone tz = dbFormatter.getTimeZone();
System.out.println(tz.getDisplayName());
dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
System.out.println(dbFormatter.format(scheduledDate));
Produces the following:
Fri Sep 26 20:30:00 CDT 2008
Friday, September 26, 2008 08:30 PM Eastern Standard Time
Eastern Standard Time
Friday, September 26, 2008 08:30 PM Central Daylight Time
I actually found this to be somewhat surprising. But, I guess that shows that the answer to your question is to simply call getTimeZone on the formatter after you've parsed.
Edit:
The above was run with Sun's JDK 1.6.
#Ed Thomas:
I've tried something very similar to your example and I get very different results:
String testString = "Friday, September 26, 2008 8:30 PM Pacific Standard Time";
DateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
System.out.println("The default TimeZone is: " + TimeZone.getDefault().getDisplayName());
System.out.println("DateFormat timezone before parse: " + df.getTimeZone().getDisplayName());
Date date = df.parse(testString);
System.out.println("Parsed [" + testString + "] to Date: " + date);
System.out.println("DateFormat timezone after parse: " + df.getTimeZone().getDisplayName());
Output:
The default TimeZone is: Eastern Standard Time
DateFormat timezone before parse: Eastern Standard Time
Parsed [Friday, September 26, 2008 8:30 PM Pacific Standard Time] to Date: Sat Sep 27 00:30:00 EDT 2008
DateFormat timezone after parse: Eastern Standard Time
Seems like DateFormat.getTimeZone() returns the same TimeZone before and after the parse()... even if I throw in an explicit setTimeZone() before calling parse().
Looking at the source for DateFormat and SimpleDateFormat, seems like getTimeZone() just returns the TimeZone of the underlying Calendar... which will default to the Calendar of the default Locale/TimeZone unless you specify a certain one to use.
I recommend checking out the Joda Time date and time API. I have recently been converted to a believer in it as it tends to be highly superior to the built-in support for dates and times in Java. In particular, you should check out the DateTimeZone class. Hope this helps.
http://joda-time.sourceforge.net/
http://joda-time.sourceforge.net/api-release/index.html
tl;dr
ZonedDateTime.parse(
"Friday, September 26, 2008 8:30 PM Eastern Daylight Time" ,
DateTimeFormatter.ofPattern( "EEEE, MMMM d, uuuu h:m a zzzz" )
).getZone()
java.time
The modern way is with the java.time classes. The Question and other Answers use the troublesome old legacy date-time classes or the the Joda-Time project, both of which are now supplanted by the java.time classes.
Define a DateTimeFormatter object with a formatting pattern to match your data.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEEE, MMMM d, uuuu h:m a zzzz" );
Assign a Locale to specify the human language of the name-of-day and name of month, as well as the cultural norms for other formatting issues.
f = f.withLocale( Locale.US );
Lastly, do the parsing to get a ZonedDateTime object.
String input = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time" ;
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
zdt.toString(): 2008-09-26T20:30-04:00[America/New_York]
You can ask for the time zone from the ZonedDateTime, represented as a ZoneId object. You can then interrogate the ZoneId if you need more info about the time zone.
ZoneId z = zdt.getZone();
See for yourself in IdeOne.com.
ISO 8601
Avoid exchanging date-time data in this kind of terrible format. Do not assume English, do not accessorize your output with things like the name-of-day, and never use pseudo-time-zones such as Eastern Daylight Time.
For time zones: Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
For serializing date-time values to text, use only the ISO 8601 formats. The java.time classes use these formats by default when parsing/generating strings to represent their value.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Well as a partial solution you could use a RegEx match to get the timezone since you will always have the same text before it. AM or PM.
I don't know enough about Java timezones to get you the last part of it.
The main difference between Date and Calendar is, that Date is just a value object with no methods to modify it. So it is designed for storing a date/time information somewhere. If you use a Calendar object, you could modify it after it is set to a persistent entity that performs some business logic with the date/time information. This is very dangerous, because the entity has no way to recognize this change.
The Calendar class is designed for operations on date/time, like adding days or something like that.
Playing around with your example I get the following:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class TimeZoneExtracter {
public static final void main(String[] args) throws ParseException {
DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
System.out.println(dbFormatter.getTimeZone());
dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time");
System.out.println(dbFormatter.getTimeZone());
}
}
Output:
sun.util.calendar.ZoneInfo[id="Europe/Berlin"...
sun.util.calendar.ZoneInfo[id="Africa/Addis_Ababa"...
Is this the result you wanted?
Ed has it right. you want the timeZone on the DateFormat object after the time has been parsed.
String rawDate = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time";
DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
Date scheduledDate = dbFormatter.parse(rawDate);
System.out.println(rawDate);
System.out.println(scheduledDate);
System.out.println(dbFormatter.getTimeZone().getDisplayName());
produces
Friday, September 26, 2008 8:30 PM Eastern Daylight Time
Fri Sep 26 20:30:00 CDT 2008
Eastern Standard Time