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);
}
Related
I want to get current time specifically in English to save it in Database,
to get Current time i use function
private String get_current_Time() {
String CURRENT_TIME_FORMAT = "yyyy_MM_dd_HH_hh_mm_ss_a_MMMM_MMM_EEEE_EE";
return (String) DateFormat.format(CURRENT_TIME_FORMAT, Calendar.getInstance().getTime());
}
but when i set Locale to different language it gives me current time in that language.
for example if i set
conf.setLocale(new Locale("mr"));
it gives me date in marathi. I specifically want it in English. How to do it.
And Also how to change the language of Date once it is saved.I mean if I have saved date in English and while display i want that date to be shown in some other language, how to do it.?
As ADM suggested. new function that worked
public String get_current_Time() {
String CURRENT_TIME_FORMAT = "yyyy_MM_dd_HH_hh_mm_ss_a_MMMM_MMM_EEEE_EE";
SimpleDateFormat dateFormat = new SimpleDateFormat(CURRENT_TIME_FORMAT, Locale.ENGLISH);
return dateFormat.format(Calendar.getInstance().getTime());
}
So now it always returns Date in English
This should fix your issue! Try any of these
here is a simple tutorial
For java.util.Date, just create a new Date()
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
log.d(dateFormat.format(date)); //2016/11/16 12:08:43
For java.util.Calendar, uses Calendar.getInstance()
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
log.d(dateFormat.format(cal)); //2016/11/16 12:08:43
For java.time.LocalDateTime, uses LocalDateTime.now()
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
log.d(dtf.format(now)); //2016/11/16 12:08:43
For java.time.LocalDate, uses LocalDate.now()
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate localDate = LocalDate.now();
log.d(dtf.format(localDate)); //2016/11/16
Currently, I format the date like that:
DateFormat timeFormat = android.text.format.DateFormat.getDateFormat(
MyApplication.getInstance().getApplicationContext());
String dateFormatted = timeFormat.format(dateTime.toDate());
The result is for example: "23-07-2016" (for french mobile); or "16-07-23" (for canadian mobile), etc.
In all cases, I want year is formatted on 2 digits:
"23-07-2016" will become "23-07-16"
"16-07-23" will stay the same
...
Ps: for information I use Yoda Date Time library.
How to do that please?
Try using SimpleDateFormat, for example:
long date = <your UTC time in milliseconds>;
SimpleDateFormat formatter = new SimpleDateFormat ("d-MM-yyyy");
String s = formatter.format (date);
See API spec for details.
If by "android mobile format" you mean the date format which the user selected in android settings, you can get this value with
android.text.format.DateFormat.getDateFormat(context)
as you show in your sample code. After that, you'll probably need to parse it and substitute 4 digit year patterns with 2 digit year patterns and finish by using SimpleDateFormat as I show above.
OK I found a great solution. It's a workaround to modify directly the original pattern:
DateFormat timeFormat = DateFormat.getDateFormat(
MyApplication.getInstance().getApplicationContext());
if (timeFormat instanceof SimpleDateFormat) {
String pattern = ((SimpleDateFormat) timeFormat).toPattern()
// Change year format on 2 digits
pattern = pattern.replaceAll("yyyy", "yy");
timeFormat = new SimpleDateFormat(pattern);
}
return timeFormat.format(dateTime.toDate());
Thanks guys
I made a few adjustments:
public static String formatDate2DigitYear(#Nullable Date date) {
if (date == null)
return "";
DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(App.get());
if (dateFormat instanceof SimpleDateFormat) {
String pattern = ((SimpleDateFormat) dateFormat).toPattern();
if (pattern.matches("^[^y]*yyyy[^y]*$")) {
pattern = pattern.replaceAll("yyyy", "yy");
} else if (pattern.matches("^[^y]*y[^y]*$")) {
pattern = pattern.replaceAll("y", "yy");
}
dateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
}
return dateFormat.format(date);
}
I want to know if there is a way to get the format that is currently being used by the system.
As of now i am using the Joda Time library and manually specifying the foramt that i expect the date to be in.
private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(event_date, formatter);
This is of course not the best idea to hardcode the pattern,so is there a way i can get the pattern from the system?
You can use something like this:
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String pattern = ((SimpleDateFormat)formatter).toPattern();
String localPattern = ((SimpleDateFormat)formatter).toLocalizedPattern();
You can do like this:
String datePattern;
String timePattern;
void loadDateTimePattern(Context context) {
SimpleDateFormat dateFormat = (SimpleDateFormat) DateFormat.getDateFormat(context);
SimpleDateFormat timeFormat = (SimpleDateFormat) DateFormat.getTimeFormat(context);
datePattern = dateFormat.toPattern();
timePattern = timeFormat.toPattern();
}
DateTimeFormatter timeFormatter = DateTimeFormat.forPattern(timePattern);
DateTimeFormatter timeFormatterFull = DateTimeFormat.forPattern(datePattern + ", " + timePattern);
My date is in a string in the format "2013-12-31". I want to convert this to a local date based upon the user's device setting but only show the month and day. So if the user's device is set to German, the date should be converted to "31.12". In Germany, the day comes first followed by the month. I don't want the year to be included.
For Build.VERSION.SDK_INT < 18 I could not find a way to obtain a month/day format that obeys user preferences. This answer works if you are willing to accept month/day in user's locale default pattern (not their preferred order or format). My implementation uses the full numeric format in versions less than 18 or if any issues are encountered in the following carefully programmed series of steps.
Get user's numeric date format pattern as String
Reduce pattern to skeleton format without symbols or years
Obtain localized month/day format with DateFormat.getBestDateTimePattern
Reorder localized month/day format according to user preferred order. (key assumption: days and months can be naively swapped for all localized numeric formats)
This should result in a month/day pattern that obeys user's preference in localized formatting.
Get user date pattern string per this answer:
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
if (shortDateFormat instanceof SimpleDateFormat) {
String textPattern = ((SimpleDateFormat) shortDateFormat).toPattern();
}
Reduce pattern to day/month skeleton by removing all characters not 'd' or 'M', example result:
String skeletonPattern = 'ddMM'
Get localized month/day format:
String workingFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeletonPattern);
(note: this method requires api 18 and above and does not return values in user-preferred order or format, hence this long-winded answer):
Get user preferred date order ('M', 'd', 'y') from this method:
char[] order = DateFormat.getDateFormatOrder(context);
(note: I suppose you could parse the original pattern to get this information too)
If workingFormat is in the correct order, your job is finished. Otherwise, switch the 'd's and the 'M's in the pattern.
The key assumption here is that days and months can be naively swapped for all localized numeric formats.
DateFormat monthDayFormat = new SimpleDateFormat(workingFormat);
I think, this is the simplest solution for apps targeting API > 17:
dateFormat = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMM dd"), Locale.getDefault())
A bit late, bit I also faced the same issue. That is how I solved it:
String dayMonthDateString = getDayMonthDateString("2010-12-31", "yyyy-MM-dd", Locale.GERMANY);
Log.i("customDate", "dayMonthDateString = " + dayMonthDateString);
private String getDayMonthDateString(String dateString, String dateFormatString, Locale locale)
{
try
{
boolean dayBeforeMonth = defineDayMonthOrder(locale);
String calendarDate = dateString;
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatString);
Date date = dateFormat.parse(calendarDate);
SimpleDateFormat newDateFormat;
if (dayBeforeMonth)
{
newDateFormat = new SimpleDateFormat("dd.MM", locale);
}
else
{
newDateFormat = new SimpleDateFormat("MM.dd", locale);
}
return newDateFormat.format(date);
}
catch (ParseException e)
{
e.printStackTrace();
}
return null;
}
private boolean defineDayMonthOrder(Locale locale) throws ParseException
{
String day = "10";
String month = "11";
String year = "12";
String calendarDate = day + "." + month + "." + year;
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy");
Date date = format.parse(calendarDate);
String localizedDate = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT, locale).format(date);
int indexOfDay = localizedDate.indexOf(day);
int indexOfMonth = localizedDate.indexOf(month);
return indexOfDay < indexOfMonth ? true : false;
}
Let me know of any questions you could have related to the solution.
Keep it simple, we already have a method for this (API 18+):
String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd");
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault());
String output = format.format(currentTimeMs);
Today its 2019 July 18:
In Europe, the output will be
18.07.2019
In the US, the output will be:
07/18/2019
This works:
String dtStart = "2010-12-31";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(dtStart);
SimpleDateFormat df = (SimpleDateFormat)
DateFormat.getDateInstance(DateFormat.SHORT);
String pattern = df.toLocalizedPattern().replaceAll(".?[Yy].?", "");
System.out.println(pattern);
SimpleDateFormat mdf = new SimpleDateFormat(pattern);
String localDate = mdf.format(date);
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat outputFormat = new SimpleDateFormat("dd.MM");
try {
Date date = inputFormat.parse("2013-12-31");
String out = outputFormat.format(date);
// out is 31.12
} catch (ParseException e) {
e.printStackTrace();
}
I have a date/time that is specified in milliseconds which is retrieved by:
Calendar.getInstance().getTimeInMillis();
I would like to format this to a string that represents the date and time in whatever the local format is on the device. For example:
US: 12/15/2013 10:30 pm
Germany: 15.12.2013 22:30
I shouldn't have to specify the formatting such as:
SimpleDateFormat outputFormat = new SimpleDateFormat("MMM dd, yyyy h:mm a");
Is there an API that handles local formatting?
See this code
String myformat = android.provider.Settings.System.getString(getContentResolver(), android.provider.Settings.System.DATE_FORMAT);
DateFormat dateFormat;
if (TextUtils.isEmpty(myformat)) {
dateFormat = android.text.format.DateFormat.getMediumDateFormat(getApplicationContext());
} else {
dateFormat = new SimpleDateFormat(format);
}
so dateformat will match with your device date
check DateFormat. Specially
public static final DateFormat getDateInstance(int style,
Locale aLocale)
Here is an example. See if it can help.
I guess this is what you are looking for:
Locale locale = Locale.getDefault();
Date today = new Date();
SimpleDateFormat.SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.LONG, SimpleDateFormat.LONG, locale).format(today));
where you need to check locale and pass its value accordingly.
As an option you can store a format string in string resources to make it available via
getResources().getString(R.string.format)
Then just put strings you need to locale folders, for example:
res/values-en/strings.xml
res/values-fr/strings.xml