Java - Not the expected format from Locale - java

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.

Related

Calendar: how to get string “10:00 AM”

I’m trying to get a string like e.g. “10:00 AM”
int numberOfHourFrom_0_to_23=10;
Calendar m_auxCalendar = new GregorianCalendar();
m_auxCalendar.set(Calendar.HOUR, numberOfHourFrom_0_to_23 +12);//+12 makes it work correctly during PM hours, but not sure why.
m_auxCalendar.set(Calendar.MINUTE,0);
Date mdate=m_auxCalendar.getTime();
String mstring = DateFormat.getTimeInstance(DateFormat.SHORT).format(mdate);
If I use my Android phone during PM hours, this code works correctly (I get “10:00 AM”); however, if I use my phone during AM hours, I get “10:00 PM” instead of “10:00 AM”
java.time through desugaring
Consider using java.time, the modern Java date and time API, for your time work.
DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
int numberOfHourFrom0To23 = 10;
LocalTime time = LocalTime.of(numberOfHourFrom0To23, 0);
String mstring = time.format(timeFormatter);
System.out.println(mstring);
Output in US locale is (no surprises):
10:00 AM
A LocalTime is a time of day with no date, so seems to be all that you need here.
What went wrong in your code?
Unexpectedly Calendar.HOUR refers to hour within AM or PM, from 0 through 11. I never understood for what this is useful. When you create a GregorianCalendar in the morning and set its HOUR to 10, you get 10 AM. When you do the same in the afternoon, you get 10 PM. You tried to compensate by adding 12 hours. Now you set the hour to 22 even though the range was o through 11. Any decent class would throw an IllegalArgumentException (or similar). Not a Calendar object with default settings. Instead it adjusts the time to 10 AM on the next day. And now when you run your code in the morning, you get 10 PM, as you observed.
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 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.
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.
Related question: Difference between Calendar.HOUR and Calendar.HOUR_OF_DAY?
Documentation of Calendar.HOUR
I had solved it in a different way. Maybe, it helps you. But unfortunately, I couldn't try the code on Android...
Here is my code:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
// other code...
int numberOfHourFrom_0_to_23 = 15;
String hour = numberOfHourFrom_0_to_23 + ""; // you need a string for the following parsing
String mstring = "";
// you have to do it here, because in the other case you do it in the try block,
// you wouldn't have access on it after finishing it
try{
DateFormat hh = new SimpleDateFormat("hh");
// your input date format, in this case only hours
Date date = hh.parse(hour);
/* you have to parse the value of the string to a Date object,
can throw a 'ParseException' exception --> try-catch */
SimpleDateFormat targetFromat = new SimpleDateFormat("hh aa");
// your target format, 'aa' is for AM/PM
mstring = targetFromat.format(date);
// the method formats the time to the new format (incl. AM/PM)
} catch(ParseException e){
// exception threw by parse in the class Date
System.err.println("There was an error during parsing the initial string.");
e.printStackTrace();
}
System.out.println(mstring); // test output, in this case: 03 PM
Maybe is this article interesting for you: https://beginnersbook.com/2017/10/java-display-time-in-12-hour-format-with-ampm/ (it helped me by this answer).
UPDATE:
After reading the comment from #Ole V.V. (thank you for your correction!), I look at the class DateTimeFormatter and I want to add the code here (it is much simpler as my first code!):
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
// other code...
int numberOfHourFrom_0_to_23 = 15;
LocalTime time = LocalTime.of(numberOfHourFrom_0_to_23, 0, 0);
// parameters: hour, minute, second
String formatPattern = "hh a";
// the pattern, "hh" is for the two hours positions and "a" for AM/PM
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
String mstring = formatter.format(time);
// formatting the value and solve it as a String
System.out.println(mstring); // test output, in this case: 03 PM

Numeric date format

How to change date format from 14-feb-2019 to 14-02-2019 in android studio, actually I am picking my system date but I want to change Feb to month number in Android Studio, here is my code snippets:
eddate = (EditText) findViewById(R.id.editdate);
edtime = (EditText) findViewById(R.id.editime);
eddate.setFocusable(false);
Calendar calendar = Calendar.getInstance();
String currentDate = DateFormat.getDateInstance().format(calendar.getTime());
String[] arr=currentDate.split(" ");
String date=arr[0]+"-"+arr[1]+"-"+arr[2];
// Toast.makeText(this, ""+date, Toast.LENGTH_SHORT).show();
eddate.setText(date);
You are using the built-in date format for your locale, which is a good idea. It’s simple, you are exploiting that someone knows what that format looks like, and your code lends itself well to internationalization. When you do that, you can choose how long or short of a format you want. You probably did something equivalent to the following:
ZoneId zone = ZoneId.of("Asia/Karachi");
Locale pakistan = Locale.forLanguageTag("en-PK");
DateTimeFormatter mediumFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(pakistan);
LocalDate today = LocalDate.now(zone);
System.out.println(today.format(mediumFormatter));
15-Feb-2019
In my snippet I have specified a medium format. I think that your best bet is to use the short format instead:
DateTimeFormatter shortFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.SHORT).withLocale(pakistan);
System.out.println(today.format(shortFormatter));
15/02/2019
This uses slashes instead of hyphens. I would trust that this is how people in your culture generally will expect to see a date when written in a short format. And you’re saved of your string manipulation or other hand formatting.
In my snippets I am using java.time, the modern Java date and time API. Calendar and DateFormat are long outdated, the latter in particular notoriously troublesome. The modern API is so much nicer to work with.
Disclaimer: I have run the snippets on my Java 10. Output on Android may vary. I wouldn’t be too worried. In all cases the built-in localized formats have been chosen with care.
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) 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 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.
Try this will help you
public class Test {
public static void main(String[] args) {
String parseddate = parseDateToddMMyyyy("14-feb-2019");
System.out.println(parseddate);
}
public static String parseDateToddMMyyyy(String time) {
String outputPattern = "dd-MM-yyyy";
String inputPattern= "dd-MMM-yyyy";
SimpleDateFormat inputFormat = new SimpleDateFormat(inputPattern);
SimpleDateFormat outputFormat = new SimpleDateFormat(outputPattern);
Date date = null;
String str = null;
try {
date = inputFormat.parse(time);
str = outputFormat.format(date);
} catch (ParseException e) {
e.printStackTrace();
}
return str;
}
}
String dateFormat= "dd-MM-yyyy";
Date date = calendar.getTime();
String dateText= new SimpleDateFormat(dateFormat).format(date);

Display timezone name in locale Java

I have this piece of code in Java
public static void main(String[] args) {
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
System.out.println(tz.getDisplayName(new Locale("ja-JP")));
}
It displays the output "Pacific Standard Time". I would think, it should display this timezone in Japanese? Is this not how this library is supposed to behave?
Use Java's japanese Locale, not your own
System.out.println(tz.getDisplayName(Locale.forLanguageTag("ja-JP")));
or better yet
System.out.println(tz.getDisplayName(Locale.JAPAN));
See here for supported locales in Java 8.

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.

Custom date format in android for given locale

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.

Categories

Resources