I receive the date from API like this:
2020-09-10T20:00:00.000Z
when I convert this date, It shows SEPTEMBER 10, 2020 8:00 p. m.
I need show the month in Spanish, e.g Septiembre or Sep
I recommend you do it with the modern java.time date-time API and the corresponding formatting API (package, java.time.format) instead of with the outdated and error-prone java.util date-time API and SimpleDateFormat. Learn more about the modern date-time API from Trail: Date Time. If your Android API level is still not compliant with Java8, check How to use ThreeTenABP in Android Project and Java 8+ APIs available through desugaring.
Do it as follows using the modern date-time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// The given date-time string
String strDateTime = "2020-09-10T20:00:00.000Z";
// Parse the given date-time string into OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
// Define the formatter for output in a custom pattern and in Spanish Locale
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM dd, uuuu hh:mm a", new Locale("es", "ES"));
// Print instant using the defined formatter
String formatted = formatter.format(odt);
System.out.println(formatted);
}
}
Output:
septiembre 10, 2020 08:00 p. m.
If you still want to use the legacy date-time and formatting API, you can do it as follows:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
// The given date-time string
String strDateTime = "2020-09-10T20:00:00.000Z";
// Define the formatter to parse the input string
SimpleDateFormat inputFormatter = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
// Parse the given date-time string into java.util.Date
Date date = inputFormatter.parse(strDateTime);
// Define the formatter for output in a custom pattern and in Spanish Locale
SimpleDateFormat outputFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm a", new Locale("es", "ES"));
// Print instant using the defined formatter
String formatted = outputFormatter.format(date);
System.out.println(formatted);
}
}
Output:
septiembre 10, 2020 08:00 p. m.
You can try something like this (it returns date in format: 10 de septiembre de 2020 20:00):
val format: DateFormat = DateFormat.getDateTimeInstance(
DateFormat.LONG, // date format
DateFormat.SHORT, // time format
Locale("es", "ES") // Spanish Locale
)
val dateTime = "2020-09-10T20:00:00.000Z"
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale("es", "ES"))
val date: Date = simpleDateFormat.parse(dateTime)!! // without validation
println(format.format(date)) // it prints `10 de septiembre de 2020 20:00`
Related
I'm trying to display an incoming ISO Date like (2021-02-15T00:00:00.000Z) to a Textview in the following format: "dd MM yyyy".
But I get the following error when parsing the date.
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.text.ParseException: Unparseable date: "2021-02-15T00:00:00.000Z"
at java.text.DateFormat.parse(DateFormat.java:362)
Here is the Kotlin code:
val format = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'",
Locale.getDefault()
)
val initialConvertedDate = format.parse(customfield.value)
val simpleDateFormat = SimpleDateFormat(
"dd MM yyyy",
Locale.getDefault()
)
val finalDate = simpleDateFormat.format(initialConvertedDate)
tv2.text = finalDate
Use the pattern, yyyy-MM-dd'T'HH:mm:ss.SSSXXX where X truly represents the timezone offset. In your date-time string, the timezone offset is Z which stands for Zulu and specifies UTC (timezone offset of +00:00 hours).
The format that you have used has two problems:
It makes Z as a character literal and therefore it does not represent timezone offset.
It does not specify fraction-of-second i.e. SSS.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String args[]) throws ParseException {
String strDateTime = "2021-02-15T00:00:00.000Z";
SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.getDefault());
Date date = sdfInput.parse(strDateTime);
SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MM yyyy");
sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String formatted = sdfOutput.format(date);
System.out.println(formatted);
}
}
Output:
15 02 2021
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:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String args[]) {
String strDateTime = "2021-02-15T00:00:00.000Z";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
System.out.println(odt);
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd MM yyyy");
String formatted = dtfOutput.format(odt);
System.out.println(formatted);
}
}
Output:
2021-02-15T00:00Z
15 02 2021
Note that the modern date-time API is based on ISO-8601 and therefore you do not need to use a DateTimeFormatter explicitly in order to parse a date-time string that is already in the ISO-8601 format.
Learn more about the the modern date-time API* from Trail: Date Time.
* 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'd like to get the LocalDateTime string representation of a specific date.
Currently the supplied date is still an old java.util.Date Object. But the method should use modern LocalDate API.
What I'd like to achieve is a short representation of a given date in the users current locale.
I have three cases for this:
Same day: Display only the time in users locale format
Same year: Strip the year of the display but display the rest (Day, month and time)
Else: Display the whole date in users locale
I also would like the month to be written as Jan or Feb instead of 01 or 02 if this is still in harmony with the users locale.
My problem is: How can I strip the year from the context specific DateFormat and how can I get a locale date string where month is not 01 but Jan.
This is what i have right now:
public static String getLocaleDateTimeStringShort(Context context, Date date) {
if (date != null && context != null) {
//TODO: Display Jan instead 01
LocalDateTime ld = date.toInstant().atZone(ZoneOffset.UTC).toLocalDateTime();
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);
DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(context);
if(ld.getDayOfMonth()==now.getDayOfMonth() && ld.getMonthValue()==now.getMonthValue() && ld.getYear()==now.getYear()) {
//Same day
return timeFormat.format(date);
} else if(ld.getYear()==now.getYear()){
//Same year
/* TODO: Strip year from date */
//dateFormat.
}else{
return dateFormat.format(date) + " " + timeFormat.format(date);
}
}
return null;
}
UPDATE
I noticed there might be confusion as of what i want to achieve. Let's take a look at some examples:
Using locale of Germany (dd MMM yy HH:mm) and US (yy MMM dd HH:mm):
If something happens on the same day for both locale, i'd like to display the time without the date:
Germany:
11:33
States
11:33 am (if phone is in 12h mode)
11:33 (if phone is in 24h mode)
Now, the second case would be a date within the same year:
Germany:
29 Aug 11:33
States:
Aug 29 11:33
What happened here? The normal pattern for Germany is dd MMM yyyy and for the states yyyy MMM dd. Because the year is not needed if it is the same year we are in. I'd like the year to be stripped away.
Different year:
Germany:
30 Aug 19 11:33
States
19 Aug 30 11:33
(I am actually not sure if i used the correct datetimepattern for the states, but nevertheless i think you can see the point. I'd like to keep EVERYTHING from the locale specific Date/DateTime Pattern. But strip the date.
I even though StringManipulating it and remove all the "y" out of it
Another update:
You can remove the year part from the pattern in the following way:
public class Main {
public static void main(String[] args) {
// Test patterns
String[] patterns = { "MMM d, y, h:mm a", "d MMM y, HH:mm", "y年M月d日 ah:mm", "dd.MM.y, HH:mm", "y. M. d. a h:mm",
"d MMM y 'г'., HH:mm", "dd MMM y, HH:mm", "y/MM/dd H:mm", "d. MMM y, HH:mm", "dd/MM/y h:mm a",
"dd.M.y HH:mm", "d MMM y HH:mm" };
for (String pattern : patterns) {
System.out.println(pattern.replaceAll("([\\s,.\\/]\\s*)?y+[.\\/]?", "").trim());
}
}
}
Output:
MMM d, h:mm a
d MMM, HH:mm
年M月d日 ah:mm
dd.MM, HH:mm
M. d. a h:mm
d MMM 'г'., HH:mm
dd MMM, HH:mm
MM/dd H:mm
d. MMM, HH:mm
dd/MM h:mm a
dd.M HH:mm
d MMM HH:mm
You can also check this for more explanation and a demo of the regex.
Explanation of the regex:
([\s,.\/]\s*)? specifies an optional group of a space, comma, dot or forward slash followed by any number of spaces
y+ specifies one or more y
[.\/]? specifies an optional dot or forward slash after y+
Update:
In the original answer, the date-time parts were fixed at specific locations in the pattern. I've written this update because OP has asked for the help to display locale-specific locations of date-time parts.
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// A sample java.util.Date instance
Date date = new Date();
// Convert Date into LocalDateTime at UTC
LocalDateTime ldt = date.toInstant().atZone(ZoneOffset.UTC).toLocalDateTime();
// Instantiate Locale with the default locale
Locale locale = Locale.getDefault();
// Build a pattern for date
String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM, null,
IsoChronology.INSTANCE, locale);
// Build a pattern for time
String timePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(null, FormatStyle.MEDIUM,
IsoChronology.INSTANCE, locale);
// Build a pattern for date and time
String dateTimePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM,
FormatStyle.MEDIUM, IsoChronology.INSTANCE, locale);
System.out.println("Test reslts for my default locale:");
System.out.println(ldt.format(DateTimeFormatter.ofPattern(datePattern, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(timePattern, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(dateTimePattern, locale)));
// Let's test it for the Locale.GERMANY
locale = Locale.GERMANY;
System.out.println("\nTest reslts for Locale.GERMANY:");
String datePatternGermany = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM, null,
IsoChronology.INSTANCE, locale);
String timePatternGermany = DateTimeFormatterBuilder.getLocalizedDateTimePattern(null, FormatStyle.MEDIUM,
IsoChronology.INSTANCE, locale);
String dateTimePatternGermany = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM,
FormatStyle.MEDIUM, IsoChronology.INSTANCE, locale);
System.out.println(ldt.format(DateTimeFormatter.ofPattern(datePatternGermany, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(timePatternGermany, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(dateTimePatternGermany, locale)));
// Let's test it for the Locale.US
locale = Locale.US;
System.out.println("\nTest reslts for Locale.US:");
String datePatternUS = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM, null,
IsoChronology.INSTANCE, locale);
String timePatternUS = DateTimeFormatterBuilder.getLocalizedDateTimePattern(null, FormatStyle.MEDIUM,
IsoChronology.INSTANCE, locale);
String dateTimePatternUS = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM,
FormatStyle.MEDIUM, IsoChronology.INSTANCE, locale);
System.out.println(ldt.format(DateTimeFormatter.ofPattern(datePatternUS, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(timePatternUS, locale)));
System.out.println(ldt.format(DateTimeFormatter.ofPattern(dateTimePatternUS, locale)));
}
}
Output:
Test reslts for my default locale:
30 Aug 2020
09:24:04
30 Aug 2020, 09:24:04
Test reslts for Locale.GERMANY:
30.08.2020
09:24:04
30.08.2020, 09:24:04
Test reslts for Locale.US:
Aug 30, 2020
9:24:04 AM
Aug 30, 2020, 9:24:04 AM
Original answer:
The following code has all that you need as per your question:
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// A sample java.util.Date instance
Date date = new Date();
// Convert Date into LocalDateTime at UTC
LocalDateTime ldt = date.toInstant().atZone(ZoneOffset.UTC).toLocalDateTime();
// Get the string representing just time part
String sameDayDateTime = ldt.format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.getDefault()));
System.out.println(sameDayDateTime);
// Get the string representing all parts except year
String sameYearDateTime = ldt.format(DateTimeFormatter.ofPattern("MMM dd, HH:mm:ss", Locale.getDefault()));
System.out.println(sameYearDateTime);
// Display the default string representation of the date-time
String defaultDateTimeStr = ldt.toString();
System.out.println(defaultDateTimeStr);
// Display the string representation of the date-time in custom format
String customDateTimeStr = ldt
.format(DateTimeFormatter.ofPattern("yyyy MMM dd, HH:mm:ss", Locale.getDefault()));
System.out.println(customDateTimeStr);
}
}
Output:
21:37:24
Aug 28, 21:37:24
2020-08-28T21:37:24.697
2020 Aug 28, 21:37:24
Since you want to be able to format/parse without year, you cannot use the built-in localized formats, you have to build your own format patterns.
Since some parts are optional, you need 3 patterns (full, without year, and without date). The full pattern can be re-used for parsing, by defining optional sections, and supplying the optional values using parseDefaulting().
First, here is a map defining some date/time format pattern for some locales, and a helper method for getting a particular pattern:
private static final Map<Locale, List<String>> FORMATS = Map.of(
Locale.ENGLISH , List.of("[MMM d[, uuuu], ]h:mm a", "MMM d, h:mm a", "h:mm a"),
Locale.FRENCH , List.of("[d MMM[ uuuu] ]HH:mm" , "d MMM HH:mm" , "HH:mm" ),
Locale.GERMAN , List.of("[dd.MM[.uuuu], ]HH:mm" , "dd.MM, HH:mm" , "HH:mm" ),
Locale.JAPANESE, List.of("[[uuuu/]MM/dd ]H:mm" , "MM/dd H:mm" , "H:mm" )
);
private static String getFormat(Locale locale, int index) {
List<String> formats = FORMATS.get(locale);
if (formats == null)
throw new IllegalArgumentException("Format patterns not available for locale " + locale.toLanguageTag());
return formats.get(index);
}
Map.of() and List.of() were both added in Java 9, and is used here for convenience.
To format a LocalDateTime, use this method:
static String format(LocalDateTime dateTime, Locale locale) {
LocalDate today = LocalDate.now();
if (dateTime.toLocalDate().equals(today))
return dateTime.format(DateTimeFormatter.ofPattern(getFormat(locale, 2), locale));
if (dateTime.getYear() == today.getYear())
return dateTime.format(DateTimeFormatter.ofPattern(getFormat(locale, 1), locale));
return dateTime.format(DateTimeFormatter.ofPattern(getFormat(locale, 0), locale));
}
To parse a formatted string back into a LocalDateTime, use this method, which uses the parseDefaulting() to supply today's date as default values:
static LocalDateTime parse(String dateTime, Locale locale) {
LocalDate today = LocalDate.now();
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern(getFormat(locale, 0))
.parseDefaulting(ChronoField.YEAR, today.getYear())
.parseDefaulting(ChronoField.MONTH_OF_YEAR, today.getMonthValue())
.parseDefaulting(ChronoField.DAY_OF_MONTH, today.getDayOfMonth())
.toFormatter(locale);
return LocalDateTime.parse(dateTime, formatter);
}
Test
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
FORMATS.keySet().stream().sorted(Comparator.comparing(Locale::getDisplayLanguage)).forEachOrdered(locale -> {
System.out.println(locale.getDisplayLanguage() + ":");
test(now.minusYears(1), locale);
test(now.minusDays(1), locale);
test(now, locale);
});
}
private static void test(LocalDateTime dateTime, Locale locale) {
String formatted = format(dateTime, locale);
LocalDateTime parsed = parse(formatted, locale);
System.out.printf(" %s formats to %-23s and parses back to %s%n", dateTime, formatted, parsed);
}
The stream is just used as a convenient way to sort the output.
Output
English:
2019-08-30T08:20:59.126394500 formats to Aug 30, 2019, 8:20 AM and parses back to 2019-08-30T08:20
2020-08-29T08:20:59.126394500 formats to Aug 29, 8:20 AM and parses back to 2020-08-29T08:20
2020-08-30T08:20:59.126394500 formats to 8:20 AM and parses back to 2020-08-30T08:20
French:
2019-08-30T08:20:59.126394500 formats to 30 août 2019 08:20 and parses back to 2019-08-30T08:20
2020-08-29T08:20:59.126394500 formats to 29 août 08:20 and parses back to 2020-08-29T08:20
2020-08-30T08:20:59.126394500 formats to 08:20 and parses back to 2020-08-30T08:20
German:
2019-08-30T08:20:59.126394500 formats to 30.08.2019, 08:20 and parses back to 2019-08-30T08:20
2020-08-29T08:20:59.126394500 formats to 29.08, 08:20 and parses back to 2020-08-29T08:20
2020-08-30T08:20:59.126394500 formats to 08:20 and parses back to 2020-08-30T08:20
Japanese:
2019-08-30T08:20:59.126394500 formats to 2019/08/30 8:20 and parses back to 2019-08-30T08:20
2020-08-29T08:20:59.126394500 formats to 08/29 8:20 and parses back to 2020-08-29T08:20
2020-08-30T08:20:59.126394500 formats to 8:20 and parses back to 2020-08-30T08:20
I'm trying to show the lokalize date to Chinese and Vietnamese.But somehow AM/PM is not translating to Vietnamese.
Locale locale = new Locale("vi","VN");
String p1 = "MMM dd, yyy 'at' h:mm a";
SimpleDateFormat dateFormat = new SimpleDateFormat(p1, locale);
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd, uuuu 'at' h:mm a", new Locale("vi", "VN"));
System.out.println(LocalDateTime.of(2021, 8, 4, 10, 20).format(dtf));
System.out.println(LocalDateTime.of(2021, 8, 4, 20, 30).format(dtf));
}
}
Output from a sample run:
thg 8 04, 2021 at 10:20 SA
thg 8 04, 2021 at 8:30 CH
ONLINE DEMO
Learn more about the modern Date-Time API* from Trail: Date Time.
* 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.
If you want to show AM/PM then you will try with Locale.ENGLISH:
Locale locale = Locale.ENGLISH;
String p1 = "MMM dd, yyy 'hiat' h:mm a";
SimpleDateFormat dateFormat = new SimpleDateFormat(p1, locale);
For anyone who still searching for this topic, I have written it manually. I upload my file here for you in case you don't want to write it.
Usage:
val spf = SimpleDateFormat("EEEE, dd/MM/yy hh:mm a", Locale.US)
val dateStr = spf.formatToVN(date)
I'm always getting the parse exception even if the format to check and the string value are same.
Here is the code:
String format = "EEE MMM dd HH:mm:ss z yyyy";
String value = "Mon Sep 18 10:30:06 MST 2017";
public static boolean isValidFormat(String format, String value) {
Date date = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
date = sdf.parse(value); // here it breaks
if (!value.equals(sdf.format(date))) {
date = null;
}
} catch (ParseException ex) {
ex.printStackTrace(); //java.text.ParseException: Unparseable date:
"Mon Sep 18 10:30:06 MST 2017" (at offset 0)
}
return date != null;
}
It says that your date-time string is unparseable at index 0. Index 0 is where it says Mon, so the three letter time zone abbreviation is not the first suspect. The locale is. “Mon” works as abbreviation for Monday in English, but not in very many other languages. So if your device has a non-English language setting — maybe it has even been changed recently — this will fully explain your observation.
The shortsighted solution is
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.ROOT);
I use Locale.ROOT to mean that no language specific processing should be done. If your string is in English because English is generally the language used in computing around the globe, I would consider this choice appropriate. If on the other hand it is in English because it comes from an English speaking locale, that locale will be the right one to use.
With this change, on my computer your code formats your date into Mon Sep 18 11:30:06 MDT 2017, which, as you can see is not the same as the value we started out from, so your method returns false. My JVM understood MST as Mountain Standard Time, and then assumed summer time (DST) in September and formatted the string accordingly.
ThreeTenABP
That said, Date and SimpleDateFormat are long outdated classes. You should give it a thought to get rid of them and use the modern Java date and time API instead. On Android you get it in the ThreeTenABP, see this question: How to use ThreeTenABP in Android Project. Now you may do:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format, Locale.ROOT);
try {
return ZonedDateTime.parse(value, dtf).format(dtf).equals(value);
} catch (DateTimeParseException dtpe) {
dtpe.printStackTrace();
return false;
}
This behaves the same as above.
Three letter time zone abbreviations
You should avoid the three and four letter time zone abbreviations where you can. They are not standardized and generally ambiguous. MST, for example, may mean Malaysia Standard Time or Mountain Standard Time. The latter isn’t even a full time zone, since MDT is used for the greater part of the year, which caused the trouble I observed as I said above.
Instead, see if you can get a string in ISO 8601 format, like 2017-09-18T10:30:06+08:00. Second best, just get something unambiguous. One way is to include an offset from UTC rather than a time zone ID (or both).
Never use SimpleDateFormat or DateTimeFormatter without a Locale
Since the given date-time is in English, you should use Locale.ENGLISH with your date-time parser; otherwise the parsing will fail in a system (computer, phone etc.) which is using a non-English type of locale.
Also, note that the date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
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.
Demo:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Mon Sep 18 10:30:06 MST 2017";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2017-09-18T10:30:06-06:00[America/Denver]
An important note about timezone before we proceed further:
Avoid specifying a timezone with the 3-letter abbreviation. A timezone should be specified with a name in the format, Region/City e.g. ZoneId.of("Europe/London"). With this convention, the ZoneId for UTC can be specified with ZoneId.of("Etc/UTC"). A timezone specified in terms of UTC[+/-]Offset can be specified as Etc/GMT[+/-]Offset e.g. ZoneId.of("Etc/GMT+1"), ZoneId.of("Etc/GMT+1") etc.
There are some exceptional cases as well e.g. to specify the timezone of Turkey, we use
ZoneId.of("Turkey")
The following code will give you all the available ZoneIds:
// Get the set of all time zone IDs.
Set<String> allZones = ZoneId.getAvailableZoneIds();
You should ask your server application to provide you with the date-time using this convention e.g.
Mon Sep 18 10:30:06 America/Denver 2017
The above code, without any change, will work for this date-time string.
Coming back to the original topic:
By default, DateTimeFormatter#ofPattern uses the default FORMAT locale which the JVM sets during startup based on the host environment. Same is the case with SimpleDateFormat. I have tried to illustrate the problem through the following demo:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final String strDateTime = "Mon Sep 18 10:30:06 America/Denver 2017";
DateTimeFormatter dtfWithDefaultLocale = null;
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + ZonedDateTime.parse(strDateTime, dtfWithDefaultLocale));
// Setting the JVM's default locale to Locale.FRANCE
Locale.setDefault(Locale.FRANCE);
// Using DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
DateTimeFormatter dtfWithEnglishLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu", Locale.ENGLISH);
System.out.println("JVM's Locale: " + Locale.getDefault());
System.out.println("DateTimeFormatter's Locale: " + dtfWithEnglishLocale.getLocale());
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtfWithEnglishLocale);
System.out.println("Parsed with Locale.ENGLISH: " + zdt);
System.out.println("JVM's Locale: " + Locale.getDefault());
// Using DateTimeFormatter with the default Locale
dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE MMM d H:m:s z uuuu");
System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
System.out
.println("Parsed with JVM's default locale: " + ZonedDateTime.parse(strDateTime, dtfWithDefaultLocale));
}
}
Output:
JVM's Locale: en_GB
DateTimeFormatter's Locale: en_GB
Parsed with JVM's default locale: 2017-09-18T10:30:06-06:00[America/Denver]
JVM's Locale: fr_FR
DateTimeFormatter's Locale: en
Parsed with Locale.ENGLISH: 2017-09-18T10:30:06-06:00[America/Denver]
JVM's Locale: fr_FR
DateTimeFormatter's Locale: fr_FR
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon Sep 18 10:30:06 America/Denver 2017' could not be parsed at index 0
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:598)
at Main.main(Main.java:32)
The following demo, using SimpleDateFormat, is just for the sake of completeness:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
final String strDateTime = "Mon Sep 18 10:30:06 MST 2017";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d H:m:s z yyyy", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
System.out.println(date);
}
}
Output:
Mon Sep 18 18:30:06 BST 2017
Note: The java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the milliseconds from the Epoch of January 1, 1970. When you print an object of java.util.Date, its toString method returns the date-time calculated from this milliseconds value. Since java.util.Date does not have timezone information, it applies the timezone of your JVM and displays the same. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFomrat and obtain the formatted string from it.
Here is the code of dateformatter which will hep you to convert your date into any time format.
public void setDate(String date) {
dateInput = (TextView) itemView.findViewById(R.id.dateText);
DateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
try {
dateData = inputFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat outputFormat = new SimpleDateFormat("pur your desirable format");
String outputString = outputFormat.format(dateData);
dateInput.setText(outputString);
}
I use the almost use the same code as you do with only slight difference in SimpleDateFormat instantiation.
public static final String DATE_FORMAT = "EEE MMM d yyyy z HH:mm:ss";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.ROOT);
simpleDateFormat.format(date);
It returns Mon Sep 18 2017 GMT+03:00 23:04:10.
This question already has answers here:
Unfortunately MyApp has stopped. How can I solve this?
(23 answers)
Convert UTC Epoch to local date
(16 answers)
How to convert String to long in Java?
(10 answers)
Closed 1 year ago.
I am getting date value from DB as a long value. I am converting this to string to use parse function. Given below is my code
Date date1 = new SimpleDateFormat("MM/dd/yyyy").parse(strDate1);
But the app is crashing when this code is executing.it will successfully execute if the
strDate1="12/30/2012".
But i am having this value as "12302012235"(pzudo value).
How can i do this?
edit:
i am saving date value to DB as INTEGER. from DB i am getting this value and converting to string.this is the actual strDate1 value
strDate1="1346524199000"
Try the following code segment:
Calendar c = Calendar.getInstance();
c.setTimeInMillis(Long.parseLong(val));
Date d = (Date) c.getTime();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
String time = format.format(d);//this variable time contains the time in the format of "day/month/year".
Try this,
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
Date dateD=new Date();
dateD.setTime(LongTime);
date=dateFormat.format(dateD);
Java 8, Convert milliseconds long to Date as String by given date format pattern. If you have a long milliseconds and want to convert them into date string at specifies time zone and pattern, then you can use it:-
dateInMs is a long value of DateTime.
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.format(Instant.ofEpochMilli(dateInMs).atZone(ZoneId.of("Europe/London")))
java.time
The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .
Using modern date-time API:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
long input = 12302012235L;
// Get Instant from input
Instant instant = Instant.ofEpochMilli(input);
System.out.println(instant);
// Convert Instant to ZonedDateTime by applying time-zone
// Change ZoneId as applicable e.g. ZoneId.of("Asia/Dubai")
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
System.out.println(zdt);
// Format ZonedDateTime as desired
// Check https://stackoverflow.com/a/65928023/10819573 to learn more about 'u'
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/uuuu", Locale.ENGLISH);
String formatted = dtf.format(zdt);
System.out.println(formatted);
// If at all, you need java.util.Date
Date date = Date.from(instant);
}
}
Output:
1970-05-23T09:13:32.235Z
1970-05-23T10:13:32.235+01:00[Europe/London]
05/23/1970
Learn more about the modern date-time API from Trail: Date Time.
* 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.
You can try following code:
private Date getGMTDate(long date) {
SimpleDateFormat dateFormatGmt = new SimpleDateFormat(
"yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat dateFormatLocal = new SimpleDateFormat(
"yyyy-MMM-dd HH:mm:ss");
Date temp = new Date(date);
try {
return dateFormatLocal.parse(dateFormatGmt.format(temp));
} catch (ParseException e) {
e.printStackTrace();
}
return temp;
}
I hope this will help you.
Try this
Date date1 = new SimpleDateFormat("MMddyyyySSS").parse(strDate1);
Hope it will works for 12302012235 , but i assume 235 is millisec.
i got the answer.actually i wanted to convert the string to date only for comparing the values.since i am getting the value as long i directly used the compareTo function to do this.avoided the conversion of long to string and string to date conversion.thank you all for support.