Date formatting based on user locale on android - android

I want to display a date of birth based on the user locale. In my application, one of my fields is the date of birth, which is currently in the format dd/mm/yyyy. So if the user changes his locale, the date format should also change accordingly. Any pointers or code samples would really help me to overcome the problem.

You can use the DateFormat class that formats a date according to the user locale.
Example:
String dateOfBirth = "26/02/1974";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = null;
try {
date = sdf.parse(dateOfBirth);
} catch (ParseException e) {
// handle exception here !
}
java.text.DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);
String s = dateFormat.format(date);
You can use the different methods getLongDateFormat, getMediumDateFormat depending on the level of verbosity you would like to have.

While the accepted answer was correct when the question was asked, it has later become outdated. I am contributing the modern answer.
java.time and ThreeTenABP
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
LocalDate dateOfBirth = LocalDate.of(1991, Month.OCTOBER, 13);
String formattedDob = dateOfBirth.format(dateFormatter);
System.out.println("Born: " + formattedDob);
It gives different output depending on the locale setting of the JVM (usually taking from the device). For example:
Canadian French: Born: 91-10-13
Chinese: Born: 1991/10/13
German: Born: 13.10.91
Italian: Born: 13/10/91
If you want a longer format, you may specify a different format style. Example outputs in US English locale:
FormatStyle.SHORT: Born: 10/13/91
FormatStyle.MEDIUM: Born: Oct 13, 1991
FormatStyle.LONG: Born: October 13, 1991
FormatStyle.FULL: Born: Thursday, October 13, 1991
Question: Can I use java.time on Android?
DateTimeFormatter.ofLocalizedDate requires Api O minimum.
Yes, java.time works nicely on older and newer Android devices. No, it does not require API level 26 or Oreo even though a message in your Android Studio might have you think that. 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 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 either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.
Question: Can I also accept user input in the user’s local format?
Yes, you can. The formatter can also be used for parsing a string from the user into a LocalDate:
LocalDate date = LocalDate.parse(userInputString, dateFormatter);
I suggest that you first format an example date and show it to the user so that s/he can see which format your program expects for his/her locale. As example date take a date with day of month greater than 12 and year greater than 31 so that the order of day, month and year can be seen from the example (for longer formats the year doesn’t matter since it will be four digits).
Parsing will throw a DateTimeParseException if the user entered the date in an incorrect format or a non-valid date. Catch it and allow the user to try again.
Question: Can I do likewise with a time of day? A date and time?
Yes. For formatting a time of day according to a user’s locale, get a formatter from DateTimeFormatter.ofLocalizedTime. For both date and time together use one of the overloaded versions of DateTimeFormatter.ofLocalizedDateTime.
Avoid the DateFormat, SImpleDateFormat and Date classes
I recommend you don’t use DateFormat, SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the first two in particular notoriously troublesome. Instead use LocalDate, DateTimeFormatter and other classes from java.time, the modern Java date and time API.
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.time to Java 6 and 7 (ThreeTen for JSR-310).
Java 8+ APIs available through desugaring
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

As simple as
For date + time:
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT, Locale.getDefault());
For just date:
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());

Android api provide easy way to display localized date format.
The following code works.
public class FileDateUtil {
public static String getModifiedDate(long modified) {
return getModifiedDate(Locale.getDefault(), modified);
}
public static String getModifiedDate(Locale locale, long modified) {
SimpleDateFormat dateFormat = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
dateFormat = new SimpleDateFormat(getDateFormat(locale));
} else {
dateFormat = new SimpleDateFormat("MMM/dd/yyyy hh:mm:ss aa");
}
return dateFormat.format(new Date(modified));
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static String getDateFormat(Locale locale) {
return DateFormat.getBestDateTimePattern(locale, "MM/dd/yyyy hh:mm:ss aa");
}
}
You can check following code.
String koreaData = FileDateUtil.getModifiedDate(Locale.KOREA, System.currentTimeMillis());
String franceData = FileDateUtil.getModifiedDate(Locale.FRENCH, System.currentTimeMillis());
String defaultData = FileDateUtil.getModifiedDate(Locale.getDefault(), System.currentTimeMillis());
String result = "Korea : " + koreaData + System.getProperty("line.separator");
result += "France : " + franceData + System.getProperty("line.separator");
result += "Default : " + defaultData + System.getProperty("line.separator");
tv.setText(result);

To change the date format according to the locale, the following code worked to me:
String dateOfBirth = "26/02/1974";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = null;
try {
date = sdf.parse(dateOfBirth);
} catch (ParseException e) {
// handle exception here !
}
String myString = DateFormat.getDateInstance(DateFormat.SHORT).format(date);
Then when you change the locale, the date format will change based on it.
For more information about the dates patterns:
http://docs.oracle.com/javase/tutorial/i18n/format/dateFormat.html

To get the date format pattern you can do :
Format dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
String pattern = ((SimpleDateFormat) dateFormat).toLocalizedPattern();
After that, you can format your input as per the pattern.

The simple way to do it:
String AR_Format = "dd-mm-yyyy";
String EN_Format = "mm-dd-yyyy";
String getFomattedDateByLocale(Date date, String locale) {
return new SimpleDateFormat(strDateFormat, new Locale(locale)).format(date);
}
And then call it like this:
txtArabicDate.setText(getFomattedDateByLocale(new Date(), AR_Format));
txtEnglishDate.setText(getFomattedDateByLocale(new Date(), EN_Format));
Don't forget to replace new Date() by your own date variable.
Good luck.

My way, with example: UTC iso format String to android User.
//string UTC instant to localDateTime
String example = "2022-01-27T13:04:23.891374801Z"
Instant instant = Instant.parse(example);
TimeZone timeZone = TimeZone.getDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, timeZone.toZoneId());
//localDateTime to device culture string output
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
String strDate = localDateTime.toLocalDate().format(dateFormatter);
DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
String strTime = localDateTime.toLocalTime().format(timeFormatter);
//strings to views
txtDate.setText(strDate);
txtTime.setText(strTime);

Related

Converting String to Date generates different results on different devices

I am retrieving a String called date in the form 2018-09-20T17:00:00Z for example and converting it to a Date in the format Thu Oct 20 17:00:00 GMT+01:00 2018 using
SimpleDateFormat dateConvert = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US);
convertedDate = new Date();
try {
convertedDate = dateConvert.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
On different devices however I am getting different results. One gives Thu Oct 20 17:00:00 BST 2018 (British Summer Time, equivalent to GMT+01:00) but this proves problematic later on. Is there a way to ensure dates are formatted in terms of a GMT offset i.e. GMT+01:00 instead of BST?
java.time
Instant convertInstant = Instant.parse(date);
An Instant (just like a Date) represents a point in time independently of time zone. So you’re fine. As an added bonus your String of 2018-09-20T17:00:00Z is in the ISO 8601 format for an instant, so the Instant class parses it without the need for specifying the format.
EDIT: To format it into a human readable string in British Summer Time with unambiguous UTC offset use for example:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
ZonedDateTime dateTime = convertInstant.atZone(ZoneId.of("Europe/London"));
String formatted = dateTime.format(formatter);
System.out.println(formatted);
This code snippet printed:
Thu Sep 20 18:00:00 +0100 2018
18:00 is the correct time at offset +01:00. The Z at the end of the original string means offset zero, AKA “Zulu time zone”, and 17 at offset zero is the same point in time as 18:00 at offset +01:00. I took over the format pattern string from your own answer.
EDIT 2
I wanted to present to you my suggestion for rewriting the Fixture class from your own answer:
public class Fixture implements Comparable<Fixture> {
private static DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
public Instant date;
/** #param date Date string from either web service or persistence */
public Fixture(String date) {
this.date = Instant.parse(date);
}
/** #return a string for persistence, e.g., Firebase */
public String getDateForPersistence() {
return date.toString();
}
/** #return a string for the user in the default time zone of the device */
public String getFormattedDate() {
return date.atZone(ZoneId.systemDefault()).format(formatter);
}
#Override
public int compareTo(Fixture other) {
return date.compareTo(other.date);
}
#Override
public String toString() {
return "Fixture [date=" + date + "]";
}
}
This class has a natural ordering (namely by date and time) in that it implements Comparable, meaning you no longer need your DateSorter class. A few lines of code to demonstrate the use of the new getXx methods:
String date = "2018-09-24T11:30:00Z";
Fixture fixture = new Fixture(date);
System.out.println("Date for user: " + fixture.getFormattedDate());
System.out.println("Date for Firebase: " + fixture.getDateForPersistence());
When I ran this snippet in Europe/London time zone I got:
Date for user: Mon Sep 24 12:30:00 +0100 2018
Date for Firebase: 2018-09-24T11:30:00Z
So the user gets the date and time with his or her own offset from UTC as I think you asked for. Trying the same snippet in Europe/Berlin time zone:
Date for user: Mon Sep 24 13:30:00 +0200 2018
Date for Firebase: 2018-09-24T11:30:00Z
We see that the user in Germany is told that the match is at 13:30 rather than 12:30, which agrees with his or her clock. The date to be persisted in Firebase is unchanged, which is also what you want.
What went wrong in your code
There are two bugs in your format pattern string, yyyy-MM-dd'T'hh:mm:ss'Z':
Lowercase hh is for hour within AM or PM from 01 through 12 and only meaningful with an AM/PM marker. In practice you will get the correct result except when parsing an hour of 12, which will be understood as 00.
By parsing Z as a literal you are not getting the UTC offset information from the string. Instead SimpleDateFormat will use the time zone setting of the JVM. This obviously differs from one device to the other and explains why you got different and conflicting results in different devices.
The other thing going on in your code is the peculiar behaviour of Date.toString: this method grabs the JVM’s time zone setting and uses it for generating the string. So when one device is set to Europe/London and another to GMT+01:00, then equal Date objects will be rendered differently on those devices. This behaviour has confused many.
Question: Can I use java.time on Android?
Yes, java.time works nicely on 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, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom). The code above was developed and run with org.threeten.bp.Duration from the backport.
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
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.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.
Wikipedia article: ISO 8601
You are just doing step 1 of a two step process:
Parse the date to convert it to a Date object
Take this parsed Date object and format it using SimpleDateFormat again.
So, you've done step one correctly, here's what you have to do with step 2, try this:
final String formattedDateString = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'GMT'XXX yyyy").format(convertedDate);
Source
So just to add a bit of an update here. The answers that people have provided have helped massively and I now have a code that does exactly what I want, but the term 'legacy' in one of the comments makes me feel that there may be a better and longer-lasting way. Here's what currently happens in the code.
1) I fetch a football fixture which comes with a String utc date in the form 2018-09-22T11:30:00Z
2) I then parse the date using SimpleDateFormat convertUtcDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); and convertUtcDate.setTimeZone(TimeZone.getTimeZone("GMT"));
3) I then get the current time using currentTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime(); and compare the two using if(convertedDate.after(currentTime)) to find a team's next fixture. At this point I have found that a device will have these two dates in the same form, either with BST or GMT+01:00 but either way the two dates can be accurately compared.
4) I then format the date so it is in terms of a GMT offset using SimpleDateFormat convertToGmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US); and String dateString = convertToGmt.format(convertedDate);
5) For the utc date in 1) this returns Sat Sep 22 12:30:00 GMT+01:00 2018 regardless of the device. Notice that the time is different to the utc date. Not quite sure why this is the case (could be because the guy running the API is based in Germany which is an hour ahead of me here in England) but the important thing is that this time is correct (it refers to the Fulham - Watford game tomorrow which is indeed at 12:30 BST/GMT+01:00).
6) I then send this String along with a few other bits of information about the fixture to Firebase. It is important that the date be in the form GMT+01:00 rather than BST at this point because other devices may not recognise the BST form when they read that information.
7) When it comes to calling that information back from Firebase, I convert it back to a date by parsing it using SimpleDateFormat String2Date = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US); and then I can arrange the fixtures in chronological order by comparing their dates.
I would just like to reiterate that this method works. I have checked for fixtures when the time zone in England changes back to GMT+00:00 and it still works fine. I have tried to make sure that everything is done in terms of GMT so that it would work anywhere. I cannot be sure though that this would be the case. Does anyone see any flaws in this method? Could it be improved?
Edit: Here is a snippet of the code which I hope simply and accurately represents what I am doing.
public class FragmentFixture extends Fragment {
SimpleDateFormat convertUtcDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
SimpleDateFormat String2Date = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US);
SimpleDateFormat convertToGmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
private List<Fixture> fixtureList;
Date date1;
Date date2;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
convertUtcDate.setTimeZone(TimeZone.getTimeZone("GMT"));
fixtureList = new ArrayList<>();
// retrieve fixtures from API and get date for a certain fixture. I will provide an example
String date = "2018-09-22T11:30:00Z";
Date convertedDate = new Date();
try {
convertedDate = convertUtcDate.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
Date currentTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime();
if (convertedDate.after(currentTime)) {
String dateString = convertToGmt.format(convertedDate);
Fixture fixture = new Fixture(dateString);
fixtureList.add(fixture);
Collections.sort(fixtureList, new DateSorter());
}
}
public class DateSorter implements Comparator<Fixture> {
#Override
public int compare(Fixture fixture, Fixture t1) {
try {
date1 = String2Date.parse(fixture.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
try {
date2 = String2Date.parse(t1.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
return date1.compareTo(date2);
}
}
public class Fixture {
public String date;
public Fixture() {
}
public Fixture(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
}

Format Date to display dd/MM/yyyy [duplicate]

This question already has answers here:
Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java [duplicate]
(2 answers)
Closed 5 years ago.
I have a method to format date i get from the server in this format 2018-01-18T13:52:49.107Z. I want to convert this format to only show the day, month and year but it doesnt work. How do i translate this response from the server to show the date format.
This is my method below:
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.S" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
Try to change the date formate with yyyy-MM-dd'T'HH:mm:ss.SSS
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
Try this
private String formatDate(String dateString) {
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
Date d = null;
try {
d = input.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
String formatted = output.format(d);
Log.i("DATE", "" + formatted);
return formatted;
}
OUTPUT
Convert input string into a date
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
Date date = inputFormat.parse(inputString);
Format date into output format
DateFormat outputFormat = new SimpleDateFormat("dd-MM-yyyy");
String outputString = outputFormat.format(date);
Here is the code to achieve this:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateForm {
public static void main(String args[]) {
String formatted = convertDateToReadable("2018-01-18T13:52:49.107Z");
System.out.println("formatted = " + formatted);
}
public static String convertDateToReadable(String dateStr) {
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
DateFormat outputFormat = new SimpleDateFormat("yyyy/MM/dd");
Date formattedDate = null;
try {
formattedDate = inputFormat.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
String formattedDateStr = outputFormat.format(formattedDate);
return formattedDateStr;
}
}
Output = formatted = 2018/01/18
This is ISO-DATE time format.
ISO dates can be written with added hours, minutes, and seconds (YYYY-MM-DDTHH:MM:SSZ)
Date and time is separated with a capital T.
UTC time is defined with a capital letter Z.
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
TL:DR
private static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd/MM/yyyy");
private static String formatDate(String dateString) {
return Instant.parse(dateString)
.atZone(ZoneId.of("Pacific/Tarawa"))
.format(dateFormatter);
}
You need to specify time zone
Given your string 2018-01-18T13:52:49.107Z the method above returns 19/01/2018. 19?? Yes, when it’s 13:52 UTC it’s already the following day on the Tarawa Atoll. And since it is never the same date everywhere on Earth, you need to specify the time zone in which you want the date. So please substitute your desired time zone if it didn’t happen to be Pacific/Tarawa. For example Africa/Maputo or Asia/Sakhalin. Then you will get the date in that zone, formatted as specified. It will not always coincide with the date in the string (in this case Jan 18, 2018) because the string gives the date and time in UTC. To use the user’s time zone you may try specifying ZoneId.systemDefault(). This will use the JVM’s time zone setting. Beware that it is fragile, the setting may be changed under your feet from other parts of your program or other programs running in the same JVM. If you did intend to have the date in UTC as in the string, use:
return Instant.parse(dateString)
.atOffset(ZoneOffset.UTC)
.format(dateFormatter);
Now the result is guaranteed to be 18/01/2018.
java.time
I am using java.time, the modern Java date and time API. I recommend you do the same. The Date class is long outdated, and SimpleDateFormat is not only that, it is also notoriously troublesome. The modern API is so much nicer to work with.
Question: Can I use java.time on Android?
Yes, you can use java.time on Android. It just requires at least Java 6.
In Java 8 and later and on newer Android devices the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new 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.
What went wrong in your code?
The main error in your method (worse that using the outdated classes) is between the following two lines!
} catch (ParseException e) {
}
An empty catch block swallows exceptions so you don’t get to see what goes wrong. Never do that. Try for example:
} catch (ParseException e) {
System.out.println("Message: " + e.getMessage());
System.out.println("Error offset: " + e.getErrorOffset());
if (e.getErrorOffset() != -1) {
System.out.println("Error text: " + dateString.substring(e.getErrorOffset()));
}
}
This prints:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 5
Error text: 01-18T13:52:49.107Z
So your formatter cannot parse 01, the month. Check the documentation, it says about month: “ If the number of pattern letters is 3 or more, the month is interpreted as text;…”. So lets try MM instead of MMM in the format pattern string. Now we get:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 10
Error text: T13:52:49.107Z
The T is offending. Of course, it’s not in the pattern string. To indicate that a literal letter is part of the format, enclose it apostrophes: yyyy-MM-dd'T'HH:mm:ss.S. Next time your method returns:
18/01/2018
Are we through? I’d say not. You are ignoring the Z at the end. It means offset 0 from UTC or “Zulu time zone”. By ignoring it, you are parsing the date-time string as a date-time in your JVM’s default time zone, which gives an incorrect time. In newer Java versions the Z can be parsed using the format pattern letter uppercase X, either one, two or three of them. Try yyyy-MM-dd'T'HH:mm:ss.SXXX:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 22
Error text: 7Z
It seems that one S matches two digits, 10, but not the third decimal, 7. I don’t know why, but let’s put three, SSS for three decimals: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Now it works.
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.

OffsetDateTime to Date Android

I am getting an OffsetDateTime from our backend in a String format like this:
"2017-07-15T10:52:59Z"
I am trying to parse this String to a Android Date:
private SimpleDateFormat mSimpleDateFormat;
private static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
mSimpleDateFormat = new SimpleDateFormat(DATE_FORMAT_PATTERN, Locale.getDefault());
Date newDate = null;
String dateString = notice.getCreated();
try {
newDate = mSimpleDateFormat.parse(dateString);
} catch (ParseException e) {
LogHelper.showExceptionLog(MyClass.class, e);
}
It always throws:
Unparseable date: "2017-07-15T10:52:59Z"
To parse the Z (which is the UTC designator) you must use the X pattern (as explained in javadoc):
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
String dateString = "2017-07-15T10:52:59Z";
Date newDate = mSimpleDateFormat.parse(dateString);
If you use just yyyy-MM-dd'T'HH:mm:ss as a pattern, SimpleDateFormat will use the system's default timezone and ignore the Z, giving incorrect results: it'll parse the date/time as 10:52 in the default timezone, which can be different to 10:52 in UTC. By using the X pattern, you get the correct result.
I also removed the Locale because this formatter is not dealing with any locale-sensitive information (like month and day of week names), so it doesn't affect the parsing in this case (and SimpleDateFormat already uses the default locale if you don't specify one).
PS: the X pattern was introduced in JDK 7. If you're using and older version, it won't be available. In this case, you can set the UTC as a timezone of the formatter:
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
mSimpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Obviously this code is assuming that the input is always in UTC (with Z in the end).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
For Android, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need ThreeTenABP (more on how to use it here).
As the input string is in ISO 8601 format, you can easily parse it to a org.threeten.bp.OffsetDateTime:
String dateString = "2017-07-15T10:52:59Z";
OffsetDateTime odt = OffsetDateTime.parse(dateString);
You can then convert this to a java.util.Date easily, using the org.threeten.bp.DateTimeUtils class:
Date date = DateTimeUtils.toDate(odt.toInstant());
If the input is always in UTC (always with the Z in the end), you can also use a org.threeten.bp.Instant:
String dateString = "2017-07-15T10:52:59Z";
Instant instant = Instant.parse(dateString);
Date date = DateTimeUtils.toDate(instant);
The only difference is that Instant only parses UTC inputs (ending with Z) and OffsetDateTime accepts any valid UTC offset (like -03:00 or +05:30).

Parse a date-time string in ISO 8601 format without offset-from-UTC

I am parsing date of string type into Date format , but everytime got this exception
java.text.ParseException: Unparseable date: "2016-05-21T00:00:00" (at offset 4)
My code is :
String d = "2016-05-21T00:00:00";
DateFormat df = new SimpleDateFormat("yyyy MM dd HH:mm:ss", Locale.ENGLISH);
Date myDate = null;
try {
myDate = df.parse(d);
} catch (ParseException e) {
e.printStackTrace();
}
Your date string and DateFormat need to match. For your input "2016-05-21T00:00:00", the correct DateFormat is:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
tl;dr
LocalDateTime.parse( "2016-05-21T00:00:00" )
ISO 8601
The input string 2016-05-21T00:00:00 is in standard ISO 8601 format.
java.time
The java.time classes built into Java 8 and later use the ISO 8601 formats by default when parsing or generating textual representations of date-time values.
The input string lacks any offset-from-UTC or time zone info. So the string by itself is imprecise, has no specific meaning as it is not a moment on the timeline. Such values are represented in java.time by the LocalDateTime class.
String input = "2016-05-21T00:00:00";
LocalDateTime ldt = LocalDateTime.parse( input );
If you know from a larger context that the string is intended to have meaning for a certain offset-from-UTC, assign a ZoneOffset to get a OffsetDateTime object.
ZoneOffset zoneOffset = ZoneOffset.of( 5 , 30 );
OffsetDateTime odt = ldt.atOffset( zoneOffet );
Even better, if you are certain of an intended time zone, specify a ZoneId to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ldt.atZone( ZoneId );
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 the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java 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 Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
String expectedDateFormat=getDateFromString("2016-05-21 00:00:00","yyyy-MM-dd HH:mm:ss","yyyy MM dd HH:mm:ss");
This method will perform actual format to expected format.
public static String getDateFromString(String dateInString, String actualformat, String exceptedFormat) {
SimpleDateFormat form = new SimpleDateFormat(actualformat);
String formatedDate = null;
Date date;
try {
date = form.parse(dateInString);
SimpleDateFormat postFormater = new SimpleDateFormat(exceptedFormat);
formatedDate = postFormater.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return formatedDate;
}
public class test {
public static void main(String [] args) {
// ref http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss");
System.out.println("Current Date: " + simpleDateFormat.format(new Date()));
}
}
for more information on SimpleDateFormat
try this way
String d = "2016-05-21 00:00:00";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
Date myDate = null;
try {
myDate = df.parse(d);
} catch (ParseException e) {
e.printStackTrace();
}
EDIT
String d = "2016-05-21 00:00:00";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
Date myDate = null;
try {
myDate = df.parse(d);
} catch (ParseException e) {
e.printStackTrace();
}

how to get date from milliseconds in android

I have time in milliseconds, now I want to separate time and date from these milliseconds.
how can i do this???
you can use like this
Calendar cl = Calendar.getInstance();
cl.setTimeInMillis(milliseconds); //here your time in miliseconds
String date = "" + cl.get(Calendar.DAY_OF_MONTH) + ":" + cl.get(Calendar.MONTH) + ":" + cl.get(Calendar.YEAR);
String time = "" + cl.get(Calendar.HOUR_OF_DAY) + ":" + cl.get(Calendar.MINUTE) + ":" + cl.get(Calendar.SECOND);
This function will give you a String date from milliseconds
public static String getFormattedDateFromTimestamp(long timestampInMilliSeconds)
{
Date date = new Date();
date.setTime(timestampInMilliSeconds);
String formattedDate=new SimpleDateFormat("MMM d, yyyy").format(date);
return formattedDate;
}
Convert the milliseconds to Date instance and pass it to the chosen formatter:
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
String myDate = dateFormat.format(new Date(dateInMillis)));
Use a Calendar to get the values of different time fields:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timeInMillis);
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int monthOfYear = cal.get(Calendar.MONTH);
You could convert the milliseconds to a date object and then extract date in the format of a time string and another string of just the date
Further to Kiran Kumar Answer
public static String getFormattedDateFromTimestamp(long timestampInMilliSeconds, String dateStyle){
Date date = new Date();
date.setTime(timestampInMilliSeconds);
String formattedDate=new SimpleDateFormat(dateStyle).format(date);
return formattedDate;
}
java.time and ThreeTenABP
I suggest java.time, the modern Java date and time API, for your date and time work:
long millisecondsSinceEpoch = 1_567_890_123_456L;
ZonedDateTime dateTime = Instant.ofEpochMilli(millisecondsSinceEpoch)
.atZone(ZoneId.systemDefault());
LocalDate date = dateTime.toLocalDate();
LocalTime time = dateTime.toLocalTime();
System.out.println("Date: " + date);
System.out.println("Time: " + time);
Output in my time zone (Europe/Copenhagen):
Date: 2019-09-07
Time: 23:02:03.456
The date and time classes used in the other answers — Calendar, Date and SimpleDateFormat — are poorly designed and long outdated. This is why I don’t recommend using any of them but prefer java.time.
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
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.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.
You can use the Date format and set your millisecond value as a parameter to this constructor, Follow this code:
SimpleDateFormat SDF= new SimpleDateFormat("dd/MM/yyyy");
String date = SDF.format(new Date(millies)));

Categories

Resources