Which Locale (SimpleDateFormat) is "yyyy-MM-dd"? - android

I want to convert a date into "yyyy-MM-dd". I am using
val parser = SimpleDateFormat("dd-MMM-yyyy") // The original format
val formatter = SimpleDateFormat("yyyy-MM-dd")
val output = formatter.format(parser.parse(etDOB.text.toString()))
as given here. But Android studio is warning me to use SimpleDateFormat(String, Locale). Which locale should I use to get output into "yyyy-MM-dd"?
Or is there a better way to achieve this (API 21)? I also have the date in a calendar instance.

Use Locale.getDefault() in SimpleDateFormat
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())

Related

Get time from LocalDateTime

I'm looking to get the time from LocalDateTime (unless there is an easier way) with the format of HH:mm:a (12:34 pm)
Which Date/Time formatter do I want to use?
val sdf = SimpleDateFormat("HH:mm:a")
val dt = LocalDateTime.now().format(sdf)
print("Time: $dt")
I just managed to accomplish that the other way. Look at my code bellow.
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun main() {
val sdf = DateTimeFormatter.ofPattern("hh:mm:a")
val dt = LocalDateTime.now().format(sdf)
println("Time: $dt")
}
Reference:
Kotlin Program to Get Current Date/Time
tl;dr
(Using Java syntax.)
myLocalDateTime
.toLocalTime() // Extract the time only, without the date portion.
.format( // Automatically localize.
DateTimeFormatter
.ofLocalizedTime( FormatStyle.SHORT )
.withLocale( Locale.US )
)
Details
The Answer by Luiz is correct. I can show a couple of alternatives: extracting the time only, and automatically localizing.
If you want to focus on the time of day, extract a LocalTime object.
LocalTime lt = myLocalDateTime.toLocalTime() ;
Rather than hard-code a specific format, it is generally best to let java.time automatically localize.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ).withLocale( Locale.US ) ;
String output = lt.format( f ) ;

Kotlin convert DateTime to 10 digit TimeStamp

I'm trying to find out how I can convert DateTime to 10 digit timestamp in Kotlin (Android Studio), I can't find any equivalent of it in Kotlin.
For example:
I have a val with date-time value like :
val dateTime = "2020-12-13 17:54:00"
Now I want to convert it to 10 digit timestamp like "1607842496"
Please give me a simple sample to show how I can resolve this problem. Thanks in advance.
Use the SimpleDateFormat class to parse your date String to a Date object. You can then get the timestamp (in milliseconds) from that Date object like so:
val dateTime = "2020-12-13 17:54:00"
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val date = simpleDateFormat.parse(dateTime)
val timestamp = date?.time
Divide the timestamp by a 1000 to get the 10 digit (in seconds) timestamp.

Convert string into LocalDateTime

I have the following String:
18/07/2019 16:20
I try to convert this string into LocalDateTime with the following code:
val stringDate = expiration_button.text.toString()
val date = LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm")).toString()
java.time.format.DateTimeParseException: Text '18/07/2019 04:30:00'
could not be parsed: Unable to obtain LocalDateTime from
TemporalAccessor
What I'm missing?
I think this will answer your question:
val stringDate = expiration_button.text.toString()
val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm");
val dt = LocalDate.parse(stringDate, formatter);
Edit 1:
It's probably crashing because you are using a 12hr Hour, instead of a 24hr pattern.
Changing the hour to 24hr pattern by using a capital H should fix it:
val dateTime = LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
Use below to convert the time from String to LocalDateTime, but make sure you are getting the time in String form.
String str = "2016-03-04 11:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
Btw, If your String contains seconds as well like "2016-03-04 11:30: 40", then you can change your date time format to yyyy-MM-dd HH:mm:ss" as shown below:
String str = "2016-03-04 11:30: 40";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
Change your datetime format to "dd/MM/yyyy hh:mm a" and provide a string date with additional AM/PM information, e.g. val stringDate = "18/07/2019 04:20 PM" or just use the 24 hour format "dd/MM/yyyy HH:mm".
You may try using "-" instead of "/" on the date.

Use different time formats according to language

I'm supposed to show different time formats according to the language in my app. When the device is English the user should get the time format like this:
18 March 2018, 2.30 pm
But when the user's device is German he should get the time format like this:
18.03.2018, 14:30 Uhr
Is there any way to do this by formatting the time String with SimpleDateFormat or am I supposed to do this in another way and if so, how am I able to do this?
I didn't think it would work, but it did. Just put the format you like into the string xml file for me it was:
<string name="date_time_format">dd MMMM yyyy, hh.mm a</string>
<string name="date_time_format">dd.MM.yyyy, HH:mm</string>
Then use it in the SDF like this:
SimpleDateFormat fmtOut = new SimpleDateFormat(context.getString(R.string.date_time_format), Locale.getDefault());
for the "Uhr" at the end of the german format i added a placeholder String that looks like this:
<string name="date_time_string">%s</string>
<string name="date_time_string">%s Uhr</string>
and i return the formated date with the String.format() method:
return String.format(context.getString(R.string.date_time_string), fmtOut.format(date));
Try this code snippet. hope it will solve the issue.
java.sql.Date date1 = new java.sql.Date((new Date()).getTime());
SimpleDateFormat formatNowDay = new SimpleDateFormat("dd");
SimpleDateFormat formatNowYear = new SimpleDateFormat("yyyy");
SimpleDateFormat sdf12 = new SimpleDateFormat("hh:mm aa");
SimpleDateFormat sdf24 = new SimpleDateFormat("HH:mm");
SimpleDateFormat germanSdf = new SimpleDateFormat("dd.MM.yyyy");
String currentDay = formatNowDay.format(date1);
String currentYear = formatNowYear.format(date1);
String time12 = sdf12.format(date1);
String time24 = sdf24.format(date1);
String germanTime = germanSdf.format(date1);
Calendar mCalendar = Calendar.getInstance();
String currentMonth = mCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
String engTime = currentDay+" "+currentMonth+" "+currentYear+", "+time12;
String germanFormat = germanTime+", "+time24+" Uhr";
One alternative is to use a java.text.DateFormat:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.ENGLISH);
The date and time styles (first and second parameters) can be either SHORT, MEDIUM, LONG or FULL. And you can use Locale.getDefault() to get the device's default language, if you want.
I'm not sure which combination of styles give what you want - all of them gave me different outputs and none gave me the one you described.
That's because locale specific formats are embeeded in the JVM, and I'm not sure how it varies among different API levels and devices.
If the solution above works, then it's fine. Otherwise, an alternative is to make specific patterns per locale:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = // use some default pattern for other languages?
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale);
String formattedDate = sdf.format(new Date());
One detail is that, in my JVM, the AM/PM symbols for English locale are in uppercase, so you may want to adjust it by doing:
// change AM/PM to am/pm (only for English)
if ("en".equals(locale.getLanguage())) {
formattedDate = formattedDate.toLowerCase();
}
java.time API
In API level 26, you can use the java.time API. For lower levels, there's a nice backport, with the same classes and functionalities.
This is much better to work with. The code might look similar, but the classes themselves solves lots of internal issues of the old API.
You can first try to get JVM's localized patterns and see if they match your output:
Locale locale = Locale.getDefault();
FormatStyle style = FormatStyle.MEDIUM;
String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(style, style, IsoChronology.INSTANCE, locale);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
Or do the same as above:
// get device's locale
Locale locale = Locale.getDefault();
String pattern = "";
// check language
if ("en".equals(locale.getLanguage())) {
// english
pattern = "dd MMMM yyyy, h.mm a";
} else if ("de".equals(locale.getLanguage())) {
// german
pattern = "dd.MM.yyyy, HH:mm 'Uhr'";
} else {
pattern = ""; // use some default pattern?
}
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, locale);
String formattedDate = LocalDateTime.now().format(fmt);
In my tests, I've got the same problem of having uppercase AM/PM for English. You can solve this by calling toLowerCase() as above, but this API also allows you to create a more flexible formatter.
And the formatters are thread-safe (while SimpleDateFormat isn't), so you could create a static map of formatters based on the language and reuse them as many times you want:
// map of formatters
Map<String, DateTimeFormatter> formatterMap = new HashMap<>();
// English formatter
Map<Long, String> customAmPmSymbols = new HashMap<>();
customAmPmSymbols.put(0L, "am");
customAmPmSymbols.put(1L, "pm");
DateTimeFormatter f = new DateTimeFormatterBuilder()
// date/time
.appendPattern("dd MMMM yyyy, h.mm ")
// custom AM/PM symbols (lowercase)
.appendText(ChronoField.AMPM_OF_DAY, customAmPmSymbols)
// create formatter
.toFormatter(Locale.ENGLISH);
// add to map
formatterMap.put("en", f);
// German formatter
formatterMap.put("de", DateTimeFormatter.ofPattern("dd.MM.yyyy, HH:mm 'Uhr'", Locale.GERMAN));
// get device's locale
Locale locale = Locale.getDefault();
DateTimeFormatter fmt = formatterMap.get(locale.getLanguage());
if (fmt != null) {
String formattedDate = LocalDateTime.now().format(fmt);
}

ThreeTenABP not parsing date

I am trying to convert ISO 8601 time into something human readable and in the local timezone of the Android device.
String date = "2016-09-24T06:24:01Z";
LocalDate test = LocalDate.parse(date, ISO_INSTANT);
But it returns:
method threw 'org.threeten.bp.format.DateTimeParseException' exception
From reading http://www.threeten.org/threetenbp/apidocs/org/threeten/bp/format/DateTimeFormatter.html#ISO_INSTANT it seems like what I'm doing should be possible.
What am I doing wrong?
Edit
Expanded exception error:
Unable to obtain LocalDate from TemporalAccessor: DateTimeBuilder[fields={MilliOfSecond=0, NanoOfSecond=0, InstantSeconds=1474698241, MicroOfSecond=0}, ISO, null, null, null], type org.threeten.bp.format.DateTimeBuilder
Edit 2
The solution is in the answer below. For anyone that stumbles across this, if you want to specify a custom output format you can use:
String format = "MMMM dd, yyyy \'at\' HH:mm a";
String dateString = DateTimeFormatter.ofPattern(format).withZone(ZoneId.systemDefault()).format(instant);
#alex answer is correct. Here is a working example.
Instant represents a point in time. To convert to any other local types you will need timezone.
String date = "2016-09-24T06:24:01Z";
This date string is parsed using the DateTimeFormatter#ISO_INSTANT internally.
Instant instant = Instant.parse(date);
From here you can convert to other local types just using timezone ( defaulting to system time zone )
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
LocalTime localTime = instant.atZone(ZoneId.systemDefault()).toLocalTime();
Alternatively, you can use static method to get to local date time and then to local date and time.
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();
You need to use Instant.parse().
This will give you an Instant that you can combine with a time zone to create a LocalDate.
In Kotlin:
Converts to LocalDateTime directly based on your local time zone::
val instant: Instant = Instant.parse("2020-04-21T02:22:04Z")
val localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime()
Converts to Date and time separately based on your local time zone:
val localDate: LocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate()
val localTime: LocalTime = instant.atZone(ZoneId.systemDefault()).toLocalTime()

Categories

Resources