Custom date format in android for given locale - java

I'm trying to format a date for a given locale new Locale("mk", "MK"). The locale is valid, it returns the country name and language properly. I want to use custom string, in my case "E, kk:mm" or "EEEE, kk:mm". I want the output to be "сабота, 12:00", but what I get is "7, 12:00".
This is how I use it and I tried many ways, but they all seem to behave the same.
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, kk:mm", new Locale("mk", "MK));
sdf.format(new Date());
// output: 7, 12:30
Another method I tried
Calendar calendar = Calendar.getInstance(new Locale("mk", "MK"));
calendar.setTimeInMillis(new Date().getTime());
DateFormat.format("EEEE, kk:mm", calendar);
// output: Saturday, 12:30
I also tried using java.text.DateFormat instead android class, but no change.
The phone locale is set to English, but this is localized app, I want to show dates in a fixed locale format.
I've looked into many SO question regarding this issue and I wasn't able to find answer. I'm not interested in predefined formats, I want to use my own format and I want the date/month names to be formatted for the input locale.

I think the problem is that Macedonia is not a supported locale on the Android JVM. If you run your code as plain Java console app, it's fine. The method Locale.getAvailableLocales() returns 152 members in plain Java, only 88 in an Android emulator. If you have the code snippet:
Locale[] locales = Locale.getAvailableLocales();
String cCode;
for (Locale loc :locales){
cCode = loc.getCountry();
if (cCode.equalsIgnoreCase("MK"))
Toast.makeText(this, cCode, Toast.LENGTH_SHORT).show();
// Or System.out.println() in a Java app
}
Then the toast doesn't show for "MK" although it will println in the Java app

From documentation of SimpleDateFormat:
**Text**: For formatting, if the number of pattern letters is 4 or more,
the full form is used; otherwise a short or abbreviated form is used if
available. For parsing, both forms are accepted, independent of the
number of pattern letters.
So this should fix it:
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, kk:mm", new Locale("mk", "MK"));

NickT was faster :-), so just adding to his answer: if you want to see your locales supported on Android, run:
for (Locale l:Locale.getAvailableLocales()) {
Log.d(l.getDisplayCountry(),l.toString());
}
and you will see that Macedonia is not on the list.

Related

Java - Not the expected format from Locale

I'm having some issues in some countries, on this case is with the Locale("cs", "CZ") the format of the date I'm looking for is dd. MM. but is returning dd.MM., how can I solve this?
I'm trying to get the pattern doing this :
val pattern = DateFormat.getBestDateTimePattern(locale, "ddMM")
val dateFormatted = DateTimeFormatter.ofPattern(pattern,locale).withLocale(locale).format(date)
But the problem is since I'm using this Locale it's somehow assigned with an unexpected date formatter.
How can I get this dd. MM. pattern?
The code is in kotlin but i tag java so if you put a Java answer and it works I'll mark it as a correct one.
If you need a pattern for the complete date, DateTimeFormatter#ofLocalizedDate meets your requirement precisely. However, if you need to restrict it to just days and months, the options are limited. I have shown a couple of the options below:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
Locale locale = new Locale("cs", "CZ");
DateTimeFormatter dtf1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).localizedBy(locale);
// Test
String formatted = dtf1.format(LocalDate.now());
System.out.println(formatted);
// If you are required to remove year, do it explicitly
formatted = formatted.replaceAll("\\s+\\d{4}", "");
System.out.println(formatted);
// Or use a fixed format
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("dd. MM.", locale);
// Test
System.out.println(dtf2.format(LocalDate.now()));
}
}
Output:
7. 10. 2021
7. 10.
07. 10.
ONLINE DEMO
Learn more about the modern Date-Time API* from Trail: Date Time.
* 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. Note that Android 8.0 Oreo already provides support for java.time.

java.util.Locale constructor does not workwhen using "gsw" as a Swiss language locale in Java 8

The context:
A customer asked me to help him with a method to format a Joda DateTime with a Locale specified as a parameter.
The problem:
Using "gsw" (Swiss German) as a language does not seem to have an effect on the translation (falls back to English in my case).
"gsw" is part of ISO639-2 (which is ISO639 alpha-3, which the Java locale says it supports, https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html).
I verified to be 100% sure and gsw is part of alpha-3, but it wasn't part of alpha-2 (ISO639-1): https://www.loc.gov/standards/iso639-2/php/English_list.php
I've tried with other languages which are part of alpha-3 but were not present in alpha-2 and I see the same strange behavior.
Have I might not read well enough the Locale helpcenter?
The code:
//all are types belong to joda.time, except Locale, which is java.util
DateTimeZone dtZone = DateTimeZone.forID(IANATimezone);
DateTime dtus = dateTime.withZone(dtZone);
Locale locale = new Locale(Language, Region);
DateTimeFormatter dtf = DateTimeFormat.fullDateTime().withLocale(locale);

default locale and numberformat

Hi I am struggling to format numbers like the documentation for NumberFormat.getInstance() says.
(Windows 7, NetBeans, Java 7)
I have first gone into regional settings and removed us english, us english keyboards and everything. I set it all to French and France. I even rebooted my pc. My code is:
System.setProperty("user.language", "fr");
System.setProperty("user.country", "FR");
System.setProperty("user.language.display", "fr");
System.setProperty("user.country.display", "FR");
System.setProperty("user.language.format", "fr");
System.setProperty("user.country.format", "FR");
Locale locale = new Locale("French", "France");
Locale.setDefault(locale);
Locale.setDefault(Locale.Category.DISPLAY, locale);
Locale.setDefault(Locale.Category.FORMAT, locale);
java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
System.out.println(nf.format(4.5));
Despite all of this, the program prints "4.5". I don't understand, for French France this should be "4,5". What more do I need to do?
This is the problem:
Locale locale = new Locale("French", "France");
It should be:
Locale locale = new Locale("fr", "FR");
Or just use Locale.FRENCH.
Additionally, you don't need to set any properties or change the default locale. Just fetch the NumberFormat for the locale you're interested in.
It's a lot easier than that...
Locale locale = Locale.FRENCH;
will initialize the variable with the french locale, and
java.text.NumberFormat nf = java.text.NumberFormat.getInstance(locale);
will get you a NumberFormat for that locale.
EDIT: as you're using NetBeans, two tips to avoid this kind of trouble in the future:
When you type
Locale locale = new Locale(
followed by ctrl-space NetBeans will pop up a list of possible completions of that statement, with for each alternative a small window showing the JavaDoc.
Alternatively, when the cursor is on Locale NetBeans will bring up a browser window with the JavaDoc when you press Alt-F1 or rightclick, Show JavaDoc.
Java's library is well documented, and having the documentation come up with just one keystroke is a real timesaver.
This is a very old question, but I would like to report I've just found what seems to be a bug in the JVM implementation for OSX (Mac only bug).
This is a small piece of code that shows the problem:
public static void main(String[] args) {
DecimalFormatSymbols d = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
System.out.println(System.getProperty("user.language.format"));
System.out.println(System.getProperty("user.language"));
System.out.println(d.getDecimalSeparator());
System.out.println(d.getGroupingSeparator());
Locale l = Locale.getDefault();
System.out.println("Language: "+l.getLanguage());
System.out.println("Country: "+l.getCountry());
System.out.println("Variant: "+l.getVariant());
System.out.println("Tag: "+l.toLanguageTag());
Currency c = Currency.getInstance(l);
System.out.println("Code: "+c.getCurrencyCode());
NumberFormat nc = DecimalFormat.getCurrencyInstance();
NumberFormat ni = DecimalFormat.getNumberInstance();
}
In my case, the output is:
en
es
.
,
Language: es
Country: ES
Variant:
Tag: es-ES
Code: EUR
Im my operating system I've set es_ES but due to a bug. The JVM system property user.language.format is not properly initialised and this is the source of several pains.

Using DateFormat.getDateTimeInstance().format(date);

When running some tests I came across the following issue. When using:
private String printStandardDate(Date date) {
return DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT).format(date);
}
I found this produced different formats of Date depending on the location the tests where run from. So locally in windows / eclipse I got a result: 04/02/12 18:18 but on the Linux box in America I get 2/4/12 6:18 PM
This causes my Tests/Build to fail:
expected:<[04/02/12 18:18]> but was:<[2/4/12 6:18 PM]>
Could anyone explain this behavior?
That's not strange, that's exactly how it's supposed to work.
The API documentation of DateFormat.getDateTimeInstance says:
Gets the date/time formatter with the given date and time formatting styles for the default locale.
The default locale is different on your Windows system than on the Linux box in America.
If you want exact control over the date and time format, use SimpleDateFormat and specify the format yourself. For example:
private String printStandardDate(Date date) {
return new SimpleDateFormat("dd/MM/yy HH:mm").format(date);
}
Even better would be to re-use the SimpleDateFormat object, but beware that it is not thread-safe (if the method might be called from multiple threads at the same time, things will get messed up if those threads use the same SimpleDateFormat object).
private static final DateFormat DATE_FORMAT =
new SimpleDateFormat("dd/MM/yy HH:mm");
private String printStandardDate(Date date) {
return DATE_FORMAT.format(date);
}
The format is based on the default locale in your code. If you want to ensure results you must make sure to use a specific locale. The getDateTimeInstance method is overloaded to offer an alternative method that receives the locale that you want to use as parameter.
public static final DateFormat getDateTimeInstance(int dateStyle,
int timeStyle,
Locale aLocale)
If you use the same locale in both testing environments, the result should be the same.

Android Time Class format time

How do I format time using Android's Time Class.
I want to display time in this format "hh:mm AM/PM" . I have tried using the Time.format function but I'm not sure if I'm using it correctly.
Thanks
Please try this..
SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm aa");
Date dt = new Date();
String strValue = timeFormat.format(dt);
Time time = new Time();
time.set(0, 0, 17, 4, 5, 1999);
Log.i("Time", time.format("%d.%m.%Y %H:%M:%S"));
try:
String strTime = time.format("%I:%M %p");
Your answer can be derived from, but not limited to this link, a C++ reference about "ctime":
http://www.cplusplus.com/reference/ctime/strftime/
I found this link to be very helpful deciphering the string formats used in my own work.
The Android.Text.Format.Time.Format docs assumes you know something:
Where or how to read "man" page for strftime, which if you weren't familiar using Linux (or a Mac at the terminal) might require some creative web searching or know what "See man strftime for what means what." referred to. Informal as it is in official documentation, it does build off and reference what has already has come before and is left as an exercise for the developer.

Categories

Resources