Reputation: 1117
Ok, so I have a string, say "Tue May 21 14:32:00 GMT 2012" I want to convert this string to local time in the format May 21, 2012 2:32 pm. I tried SimpleDateFormat("MM dd, yyyy hh:mm a").parse(), but it threw an exception. So what should I do?
The exception is "unreported exception java.text.ParseException; must be caught or declared to be thrown."
in the line Date date = inputFormat.parse(inputText);
The code I ran on TextMate:
public class test{
public static void main(String arg[]) {
String inputText = "Tue May 22 14:52:00 GMT 2012";
SimpleDateFormat inputFormat = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss 'GMT' yyyy", Locale.US);
inputFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat out = new SimpleDateFormat("MMM dd, yyyy h:mm a");
Date date = inputFormat.parse(inputText);
String output = out.format(date);
System.out.println(output);
}
}
Upvotes: 14
Views: 26262
Reputation: 123
const val DATE_HYPHEN_FORMAT = "yyyy-MM-dd"
const val DATE_MMM_DD_YYYY_FORMAT = "MMM dd, yyyy"
const val DATE_MMMM_DD_YYYY_FORMAT = "MMMM dd, yyyy"
const val FULL_DAY_NAME_FORMAT = "EEEE"
const val DATE_EEE_DD_MMMM_YYYY_FORMAT = "EEE dd, MMMM yyyy"
const val DATE_EEEE_DD_MMMM_YYYY_FORMAT = "EEEE dd, MMMM yyyy"
const val DATETIME_24_FORMAT = "dd-MM-yyyy'T'HH:mm:ss"
const val DATETIME_24_YMD_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"
const val DATE_WITH_MONTH_NAME_MMM_DY_FORMAT = DateFormat.MEDIUM
const val DATE_WITH_MONTH_FULL_NAME_MMMM_DY_FORMAT = DateFormat.LONG
const val TIME_24H_FORMAT = "HH:mm:ss"
const val TIME_FORMAT_AM_PM = "hh:mm aa"
const val TIME_24H_FORMATWithoutSS = "HH:mm"
enum class TimeZoneTo {
NONE, UTC, LOCAL
}
fun changeFormat(
dateTime: String,
fromFormat: Int = DATE_WITH_MONTH_NAME_MMM_DY_FORMAT,
toFormat: String = DATETIME_24_FORMAT,
convertIn: TimeZoneTo = TimeZoneTo.NONE,
needOnlyTime: Boolean = false
): String {
try {
val parser = DateFormat.getDateInstance(fromFormat)
val finalDateTime = trimDateTime(dateTime)
val date = parser.parse(finalDateTime)
val sdf = SimpleDateFormat(toFormat)
return format(
date = date!!, formatter = sdf, convertIn = convertIn, needOnlyTime = needOnlyTime
)
} catch (e: AssertionError) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return dateTime // Return Same DateTime - only iff unable to change format
}
fun changeFormat(
dateTime: String,
fromFormat: String = DATETIME_24_FORMAT,
toFormat: Int = DATE_WITH_MONTH_NAME_MMM_DY_FORMAT,
convertIn: TimeZoneTo = TimeZoneTo.NONE,
needOnlyTime: Boolean = false
): String {
try {
val sfdInput = SimpleDateFormat(fromFormat, Locale.ROOT)
val finalDateTime = trimDateTime(dateTime)
val date: Date = sfdInput.parse(finalDateTime)!!
val outputFormatter = DateFormat.getDateInstance(toFormat)
return format(
date = date,
formatter = outputFormatter,
convertIn = convertIn,
needOnlyTime = needOnlyTime
)
} catch (e: AssertionError) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return dateTime // Return Same DateTime - only iff unable to change format
}
fun changeFormat(
dateTime: String,
fromFormat: String = DATETIME_24_FORMAT,
toFormat: String = DATE_HYPHEN_FORMAT,
convertInTimeZone: TimeZoneTo = TimeZoneTo.NONE,
needOnlyTime: Boolean = false
): String {
try {
val sfdInput = SimpleDateFormat(fromFormat, Locale.ROOT)
val finalDateTime = trimDateTime(dateTime)
val date: Date = sfdInput.parse(finalDateTime)!!
val sdfOutput = SimpleDateFormat(toFormat)
return format(
date = date,
formatter = sdfOutput,
convertIn = convertInTimeZone,
needOnlyTime = needOnlyTime
)
} catch (e: AssertionError) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return dateTime // Return Same DateTime - only iff unable to change format
}
// Format Given Date as per specified timeZone
private fun format(
date: Date,
formatter: DateFormat,
convertIn: TimeZoneTo,
needOnlyTime: Boolean
): String {
return when (convertIn) {
TimeZoneTo.LOCAL -> {
val zone = TimeZone.getTimeZone(Calendar.getInstance().timeZone.id)
val newDate = Date(date.time + zone.getOffset(date.time))
formatter.timeZone = zone
val result = formatter.format(newDate)
if (needOnlyTime) return result.substringAfter('T')
else result
}
TimeZoneTo.UTC -> {
formatter.timeZone = TimeZone.getTimeZone("UTC")
val result = formatter.format(date)
if (needOnlyTime) return result.substringAfter('T')
else result
}
else -> {
val result = formatter.format(date)
if (needOnlyTime) return result.substringAfter('T')
else result
}
}
}
I've created 3 overloaded methods namely changeFormat(...) with following params;
Hopefully, this may help someone in future.
Upvotes: 0
Reputation: 338730
You are using troublesome old date-time classes now supplanted by the java.time classes.
Your first example string is incorrect, as the 21st is a Monday not a Tuesday. The second example string with 22nd is correct, and used in my example code below.
Avoid using this kind of format for textual representations of date-time values. In particular, never use the 3-4 letter abbreviation such as EST
or IST
seen in this kind of format, as they are not true time zones, not standardized, and not even unique(!). Specify a proper time zone name. In this particular case, java.time is able to translate that as GMT
as UTC, but other values may fail.
String input = "Tue May 22 14:52:00 GMT 2012";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" ).withLocale ( Locale.US );
ZonedDateTime zdt = ZonedDateTime.parse ( input , f );
System.out.println ( "zdt: " + zdt );
Dump to console. The toString
method generates a String in standard ISO 8601 format, extended by appending the name of the zone in brackets. These standard formats are a much better choice for when you need to serialize date-time values to text.
System.out.println ( "zdt: " + zdt );
zdt: 2012-05-22T14:52Z[GMT]
You can generate a String to represent this value in any format you desire. Generally best to let java.time localize automatically using a Locale
and DateTimeFormatter
.
Your desired format uses a medium-length style for the date portion but a short-length style for the time-of-day portion. Fortunately the DateTimeFormatter
allows you to localize each portion separately, as seen here where we pass a pair of FormatStyle
objects.
Locale l = Locale.US; // Or Locale.CANADA_FRENCH, or Locale.ITALY, etc.
DateTimeFormatter fOutput = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.MEDIUM , FormatStyle.SHORT ).withLocale ( l );
String output = zdt.format ( fOutput );
Dump to console.
System.out.println ( "zdt: " + zdt + " | output: " + output );
zdt: 2012-05-22T14:52Z[GMT] | output: May 22, 2012 2:52 PM
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
, .Calendar
, & java.text.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.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (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.
Upvotes: 1
Reputation: 1500675
The format string you provided for parsing doesn't correspond with the text format you've actually got. You need to parse first, then format. It looks like you want:
SimpleDateFormat inputFormat = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss 'GMT' yyyy", Locale.US);
inputFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat outputFormat = new SimpleDateFormat("MMM dd, yyyy h:mm a");
// Adjust locale and zone appropriately
Date date = inputFormat.parse(inputText);
String outputText = outputFormat.format(date);
EDIT: Here's the same code in the form of a short but complete program, with your sample input:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws ParseException {
String inputText = "Tue May 21 14:32:00 GMT 2012";
SimpleDateFormat inputFormat = new SimpleDateFormat
("EEE MMM dd HH:mm:ss 'GMT' yyyy", Locale.US);
inputFormat.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
SimpleDateFormat outputFormat =
new SimpleDateFormat("MMM dd, yyyy h:mm a");
// Adjust locale and zone appropriately
Date date = inputFormat.parse(inputText);
String outputText = outputFormat.format(date);
System.out.println(outputText);
}
}
Can you compile and run that exact code?
Upvotes: 28
Reputation: 471
The method SimpleDateFormat.parse throws a parse exception.
The exception you're getting is telling you this...
The exception is "unreported exception java.text.ParseException; must be caught or declared to be thrown."
Wrap the line that does the parsing with try-catch and you should be golden..
Date d=null;
try{
d = inputFormat.parse(date);
catch(ParseException e){
// handle the error here....
}
R
Upvotes: 1
Reputation: 2562
The formatter you use to parse must be defined to the format you expect. Here is an example that works for the values you provided however you may need to change it depending on how some edge cases act for the input:
String date = "Tue May 21 14:32:00 GMT 2012";
DateFormat inputFormat = new SimpleDateFormat("EE MMM dd HH:mm:ss zz yyy");
Date d = inputFormat.parse(date);
DateFormat outputFormat = new SimpleDateFormat("MMM dd, yyy h:mm a zz");
System.out.println(outputFormat.format(d));
Upvotes: 3