This question already has answers here:
Localized date format in Java
(6 answers)
Closed 8 years ago.
I need to show date and time in this format, Date: 9th Dec, Time: 19:20
Although my following code is working fine in English, have no idea this is correct way in other languages which my application is supporting like Chinese, Thai, etc. Any idea would be appreciated? Thanks
This is my code:
private String getFormattedTime(Calendar calendar)
{
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
StringBuilder sBuilder = new StringBuilder(4);
sBuilder.append(hour);
sBuilder.append(":");
// We want to display the hour like this: 12:09,
// but by not using following code it becomes 12:9
if (minute < 10)
{
sBuilder.append("0");
}
sBuilder.append(minute);
return sBuilder.toString();
}
private String getDateSuffix( int day)
{
if (day < 1 || day > 31)
{
throw new IllegalArgumentException("Illegal day of month");
}
switch (day)
{
case 1:
case 21:
case 31:
return ("st");
case 2:
case 22:
return ("nd");
case 3:
case 23:
return ("rd");
default:
return ("th");
}
}
I would recommend that you use Joda Time.
Here is an example from their Quick Start Guide.
DateTime dt = new DateTime();
String monthName = dt.monthOfYear().getAsText();
String frenchShortName = dt.monthOfYear().getAsShortText(Locale.FRENCH);
While "Dec" could mean December or décembre, Joda will use the correct one, depending on Locale.
Since Locale.CHINESE and Locale.THAI are available, it will do the translation for you.
If you use Java 8, Joda comes with the package.
You will save yourself a mountain of work if you use this package.
I did some research based on what #MadProgrammer said and this is my code for those how have same problem. DateFormat and SimpleDateFormat Examples.
private String getFormattedDate(Calendar calendar)
{
Date date = calendar.getTime(); // out: Dec 9, 2014
// String str = DateFormat.getDateInstance().format(date);
// Log.d(TAG, str);
String str = new SimpleDateFormat("MMM d").format(date);
// Log.d(TAG, str);
return str;
}
private String getFormattedTime(Calendar calendar)
{
Date date = calendar.getTime();
String str = DateFormat.getTimeInstance(DateFormat.SHORT).format(date);
// Log.d(TAG, str);
return str;
}
Related
I checked the SimpleDateFormat javadoc, but I am not able to find a way to parse the ordinal indicator in a date format like this:
Feb 13th 2015 9:00AM
I tried "MMM dd yyyy hh:mma", but the days have to be in number for it to be correct?
Is it possible to parse the "13th" date using a SimpleDateFormat without having to truncate the string?
Java's SimpleDateFormat doesn't support an ordinal suffix, but the ordinal suffix is just eye candy - it is redundant and can easily be removed to allow a straightforward parse:
Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));
The replace regex is so simple because those sequences won't appear anywhere else in a valid date.
To handle any language that appends any length of ordinal indicator characters from any language as a suffix:
Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(?=\\D* \\d+ )\\p{L}+", ""));
Some languages, eg Mandarin, prepend their ordinal indicator, but that could be handled too using an alternation - left as an exercise for the reader :)
Java 8 answer (and Java 6 and 7) (because when this question was asked in 2015, the replacement for SimpleDateFormat was already out):
DateTimeFormatter parseFormatter = DateTimeFormatter
.ofPattern("MMM d['st']['nd']['rd']['th'] uuuu h:mma", Locale.ENGLISH);
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, parseFormatter);
With the sample date from the question this yiedls:
2015-02-13T09:00
In the format pattern [] denotes optional parts and '' denotes literal parts. So the pattern says that the number may be followed by st, nd, rd or th.
To use this in Java 6 or 7 you need ThreeTen Backport. Or for Android ThreeTenABP.
Since those suffixes are special for English, and other languages/locales have completely other usages for writing dates and times (also they don’t use AM/PM), I believe that unless you have other requirements, you should try to implement this for English dates and times only. Also you should give an English speaking locale explicitly so it will work independently of the locale setting of your computer or JVM.
I have tried to combine the best parts of answers by Hugo and myself to a duplicate question. Under that duplicate question there are still more java 8 answers. One limitation of the above code is it doesn’t have very strict validation: you will get away with Feb 13rd and even Feb 13stndrdth.
Edit: My own favourite among my answers on ordinal indicators is this one. It’s about formatting, but the formatter I present there works fine for parsing too.
In case someone finds it useful: DateTimeFormatter builder. This formatter allows you to format and to parse UK dates with ordinal suffixes (eg. "1st January 2017"):
public class UkDateFormatterBuilder
{
/**
* The UK date formatter that formats a date without an offset, such as '14th September 2020' or '1st January 2017'.
* #return an immutable formatter which uses the {#link ResolverStyle#SMART SMART} resolver style. It has no override chronology or zone.
*/
public DateTimeFormatter build()
{
return new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.parseLenient()
.appendText(DAY_OF_MONTH, dayOfMonthMapping())
.appendLiteral(' ')
.appendText(MONTH_OF_YEAR, monthOfYearMapping())
.appendLiteral(' ')
.appendValue(YEAR, 4)
.toFormatter(Locale.UK);
}
private Map<Long, String> monthOfYearMapping()
{
Map<Long, String> monthOfYearMapping = new HashMap<>();
monthOfYearMapping.put(1L, "January");
monthOfYearMapping.put(2L, "February");
monthOfYearMapping.put(3L, "March");
monthOfYearMapping.put(4L, "April");
monthOfYearMapping.put(5L, "May");
monthOfYearMapping.put(6L, "June");
monthOfYearMapping.put(7L, "July");
monthOfYearMapping.put(8L, "August");
monthOfYearMapping.put(9L, "September");
monthOfYearMapping.put(10L, "October");
monthOfYearMapping.put(11L, "November");
monthOfYearMapping.put(12L, "December");
return monthOfYearMapping;
}
private Map<Long, String> dayOfMonthMapping()
{
Map<Long, String> suffixes = new HashMap<>();
for (int day=1; day<=31; day++)
{
suffixes.put((long)day, String.format("%s%s", (long) day, dayOfMonthSuffix(day)));
}
return suffixes;
}
private String dayOfMonthSuffix(final int day)
{
Preconditions.checkArgument(day >= 1 && day <= 31, "Illegal day of month: " + day);
if (day >= 11 && day <= 13)
{
return "th";
}
switch (day % 10)
{
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
}
Plus a fragment of the test class:
public class UkDateFormatterBuilderTest
{
DateTimeFormatter formatter = new UkDateFormatterBuilder().build();
#Test
public void shouldFormat1stJanuaryDate()
{
final LocalDate date = LocalDate.of(2017, 1, 1);
final String formattedDate = date.format(formatter);
Assert.assertEquals("1st January 2017", formattedDate);
}
#Test
public void shouldParse1stJanuaryDate()
{
final String formattedDate = "1st January 2017";
final LocalDate parsedDate = LocalDate.parse(formattedDate, formatter);
Assert.assertEquals(LocalDate.of(2017, 1, 1), parsedDate);
}
}
PS. I used Greg Mattes' solution for ordinal suffixes from here:
How do you format the day of the month to say "11th", "21st" or "23rd" in Java? (ordinal indicator)
Well, no need to replace the text. The DateTimeFormatterBuilder is able to parse this as well.
First, we need to create a Map which maps day-of-month against their day-of-month-with-ordinal-suffix. That is because unfortunately, there is no standard thing, as far as I know.
static final Map<Long, String> ORDINAL_SUFFIX_MAP;
static {
Map<Long, String> map = new HashMap<>();
for (int i = 1; i <= 31; i++) {
String suffix = switch (i) {
case 1, 21, 31 -> "st";
case 2, 22 -> "nd";
case 3, 23 -> "rd";
default -> "th";
};
map.put((long) i, i + suffix);
}
ORDINAL_SUFFIX_MAP = Map.copyOf(map);
}
Then we can utilize the DateTimeFormatterBuilder as follows:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern(firstPartOfYourPattern)
.appendText(ChronoField.DAY_OF_MONTH, ORDINAL_SUFFIX_MAP)
.appendPattern(lastPartOfYourPattern)
.toFormatter(Locale.ROOT);
LocalDateTime result = LocalDateTime.parse(str, formatter);
You should be using RuleBasedNumberFormat. It works perfectly and it's respectful of the Locale.
Logcat:
FATAL EXCEPTION: main
java.lang.IllegalArgumentException: Unknown pattern character 'u'
Here is my Code:
long ticket = 1473808310826L;
SimpleDateFormat sdf = new SimpleDateFormat("u");
String test = sdf.format(ticket);
Using: JDK 8
u is used in the documentation of SimpleDateFormat:
Day number of week (1 = Monday, ..., 7 = Sunday)
The documentation of SimpleDateFormat is misleading (as of 09/16/2016, for future readers).
There is no u pattern character in Android.
From the source code of SimpleDateFormat:
static final String PATTERN_CHARS = "GyMdkHmsSEDFwWahKzZLc";
// ...
private void validatePatternCharacter(char format) {
int index = PATTERN_CHARS.indexOf(format);
if (index == -1) {
throw new IllegalArgumentException("Unknown pattern character '"
+ format + "'");
}
}
To get the current day of the week, you could do something like this:
Calendar calendar = Calendar.getInstance();
// if you do not wish to use the current time, but a specific one
// calendar.setTimeInMillis(yourTimeInMillis);
switch (calendar.get(Calendar.DAY_OF_WEEK)) {
case Calendar.MONDAY:
// monday
break;
case Calendar.TUESDAY:
// tuesday
break;
// ...
}
I checked the SimpleDateFormat javadoc, but I am not able to find a way to parse the ordinal indicator in a date format like this:
Feb 13th 2015 9:00AM
I tried "MMM dd yyyy hh:mma", but the days have to be in number for it to be correct?
Is it possible to parse the "13th" date using a SimpleDateFormat without having to truncate the string?
Java's SimpleDateFormat doesn't support an ordinal suffix, but the ordinal suffix is just eye candy - it is redundant and can easily be removed to allow a straightforward parse:
Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));
The replace regex is so simple because those sequences won't appear anywhere else in a valid date.
To handle any language that appends any length of ordinal indicator characters from any language as a suffix:
Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
.parse(str.replaceAll("(?<=\\d)(?=\\D* \\d+ )\\p{L}+", ""));
Some languages, eg Mandarin, prepend their ordinal indicator, but that could be handled too using an alternation - left as an exercise for the reader :)
Java 8 answer (and Java 6 and 7) (because when this question was asked in 2015, the replacement for SimpleDateFormat was already out):
DateTimeFormatter parseFormatter = DateTimeFormatter
.ofPattern("MMM d['st']['nd']['rd']['th'] uuuu h:mma", Locale.ENGLISH);
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, parseFormatter);
With the sample date from the question this yiedls:
2015-02-13T09:00
In the format pattern [] denotes optional parts and '' denotes literal parts. So the pattern says that the number may be followed by st, nd, rd or th.
To use this in Java 6 or 7 you need ThreeTen Backport. Or for Android ThreeTenABP.
Since those suffixes are special for English, and other languages/locales have completely other usages for writing dates and times (also they don’t use AM/PM), I believe that unless you have other requirements, you should try to implement this for English dates and times only. Also you should give an English speaking locale explicitly so it will work independently of the locale setting of your computer or JVM.
I have tried to combine the best parts of answers by Hugo and myself to a duplicate question. Under that duplicate question there are still more java 8 answers. One limitation of the above code is it doesn’t have very strict validation: you will get away with Feb 13rd and even Feb 13stndrdth.
Edit: My own favourite among my answers on ordinal indicators is this one. It’s about formatting, but the formatter I present there works fine for parsing too.
In case someone finds it useful: DateTimeFormatter builder. This formatter allows you to format and to parse UK dates with ordinal suffixes (eg. "1st January 2017"):
public class UkDateFormatterBuilder
{
/**
* The UK date formatter that formats a date without an offset, such as '14th September 2020' or '1st January 2017'.
* #return an immutable formatter which uses the {#link ResolverStyle#SMART SMART} resolver style. It has no override chronology or zone.
*/
public DateTimeFormatter build()
{
return new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.parseLenient()
.appendText(DAY_OF_MONTH, dayOfMonthMapping())
.appendLiteral(' ')
.appendText(MONTH_OF_YEAR, monthOfYearMapping())
.appendLiteral(' ')
.appendValue(YEAR, 4)
.toFormatter(Locale.UK);
}
private Map<Long, String> monthOfYearMapping()
{
Map<Long, String> monthOfYearMapping = new HashMap<>();
monthOfYearMapping.put(1L, "January");
monthOfYearMapping.put(2L, "February");
monthOfYearMapping.put(3L, "March");
monthOfYearMapping.put(4L, "April");
monthOfYearMapping.put(5L, "May");
monthOfYearMapping.put(6L, "June");
monthOfYearMapping.put(7L, "July");
monthOfYearMapping.put(8L, "August");
monthOfYearMapping.put(9L, "September");
monthOfYearMapping.put(10L, "October");
monthOfYearMapping.put(11L, "November");
monthOfYearMapping.put(12L, "December");
return monthOfYearMapping;
}
private Map<Long, String> dayOfMonthMapping()
{
Map<Long, String> suffixes = new HashMap<>();
for (int day=1; day<=31; day++)
{
suffixes.put((long)day, String.format("%s%s", (long) day, dayOfMonthSuffix(day)));
}
return suffixes;
}
private String dayOfMonthSuffix(final int day)
{
Preconditions.checkArgument(day >= 1 && day <= 31, "Illegal day of month: " + day);
if (day >= 11 && day <= 13)
{
return "th";
}
switch (day % 10)
{
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
}
Plus a fragment of the test class:
public class UkDateFormatterBuilderTest
{
DateTimeFormatter formatter = new UkDateFormatterBuilder().build();
#Test
public void shouldFormat1stJanuaryDate()
{
final LocalDate date = LocalDate.of(2017, 1, 1);
final String formattedDate = date.format(formatter);
Assert.assertEquals("1st January 2017", formattedDate);
}
#Test
public void shouldParse1stJanuaryDate()
{
final String formattedDate = "1st January 2017";
final LocalDate parsedDate = LocalDate.parse(formattedDate, formatter);
Assert.assertEquals(LocalDate.of(2017, 1, 1), parsedDate);
}
}
PS. I used Greg Mattes' solution for ordinal suffixes from here:
How do you format the day of the month to say "11th", "21st" or "23rd" in Java? (ordinal indicator)
Well, no need to replace the text. The DateTimeFormatterBuilder is able to parse this as well.
First, we need to create a Map which maps day-of-month against their day-of-month-with-ordinal-suffix. That is because unfortunately, there is no standard thing, as far as I know.
static final Map<Long, String> ORDINAL_SUFFIX_MAP;
static {
Map<Long, String> map = new HashMap<>();
for (int i = 1; i <= 31; i++) {
String suffix = switch (i) {
case 1, 21, 31 -> "st";
case 2, 22 -> "nd";
case 3, 23 -> "rd";
default -> "th";
};
map.put((long) i, i + suffix);
}
ORDINAL_SUFFIX_MAP = Map.copyOf(map);
}
Then we can utilize the DateTimeFormatterBuilder as follows:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern(firstPartOfYourPattern)
.appendText(ChronoField.DAY_OF_MONTH, ORDINAL_SUFFIX_MAP)
.appendPattern(lastPartOfYourPattern)
.toFormatter(Locale.ROOT);
LocalDateTime result = LocalDateTime.parse(str, formatter);
You should be using RuleBasedNumberFormat. It works perfectly and it's respectful of the Locale.
I want to get the last quater's last date from Java Date/Calender classes.
For example :
If current date = 3rd Oct
Lat Quater Last Date : 30th Sept.
I am able to get the same using date.getMonth() methods, but since these methods are depricated, wondering if any better way to achive the same.
for date manipulation you should use Calendar. This may not be the most efficient way, but it works for your problem:
public Date calculateLastDayOfLastQuarter(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
int year = calendar.get(Calendar.YEAR);
try {
switch (calendar.get(Calendar.MONTH)) {
case Calendar.JANUARY:
case Calendar.FEBRUARY:
case Calendar.MARCH:
return sdf.parse("31.12." + (year - 1));
case Calendar.APRIL:
case Calendar.MAY:
case Calendar.JUNE:
return sdf.parse("31.03." + year);
case Calendar.JULY:
case Calendar.AUGUST:
case Calendar.SEPTEMBER:
return sdf.parse("30.06." + year);
case Calendar.OCTOBER:
case Calendar.NOVEMBER:
case Calendar.DECEMBER:
return sdf.parse("30.09." + year);
default:
return null;
}
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
What would be the easiest way to get the current day of the week in Android?
The Java Calendar class works.
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
switch (day) {
case Calendar.SUNDAY:
// Current day is Sunday
break;
case Calendar.MONDAY:
// Current day is Monday
break;
case Calendar.TUESDAY:
// etc.
break;
}
For much better datetime handling consider using the Java 8 time API:
String day = LocalDate.now().getDayOfWeek().name()
To use this below Android SDK 26 you'll need to enable Java 8 desugaring in build.gradle:
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
}
More information on Android's Java 8 support: https://developer.android.com/studio/write/java8-support
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
// 3 letter name form of the day
System.out.println(new SimpleDateFormat("EE", Locale.ENGLISH).format(date.getTime()));
// full name form of the day
System.out.println(new SimpleDateFormat("EEEE", Locale.ENGLISH).format(date.getTime()));
Result (for today):
Sat
Saturday
UPDATE: java8
LocalDate date = LocalDate.now();
DayOfWeek dow = date.getDayOfWeek();
System.out.println("Enum = " + dow);
String dayName = dow.getDisplayName(TextStyle.FULL, Locale.ENGLISH);
System.out.println("FULL = " + dayName);
dayName = dow.getDisplayName(TextStyle.FULL_STANDALONE, Locale.ENGLISH);
System.out.println("FULL_STANDALONE = " + dayName);
dayName = dow.getDisplayName(TextStyle.NARROW, Locale.ENGLISH);
System.out.println("NARROW = " + dayName);
dayName = dow.getDisplayName(TextStyle.NARROW_STANDALONE, Locale.ENGLISH);
System.out.println("NARROW_STANDALONE = " + dayName);
dayName = dow.getDisplayName(TextStyle.SHORT, Locale.ENGLISH);
System.out.println("SHORT = " + dayName);
dayName = dow.getDisplayName(TextStyle.SHORT_STANDALONE, Locale.ENGLISH);
System.out.println("SHORT_STANDALONE = " + dayName);
Result (for today):
Enum = SATURDAY
FULL = Saturday
FULL_STANDALONE = Saturday
NARROW = S
NARROW_STANDALONE = 6
SHORT = Sat
SHORT_STANDALONE = Sat
Java 8 datetime API made it so much easier :
LocalDate.now().getDayOfWeek().name()
Will return you the name of the day as String
Output : THURSDAY
Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
or
new GregorianCalendar().get(Calendar.DAY_OF_WEEK);
Just the same as in Java, nothing particular to Android.
public String weekdays[] = new DateFormatSymbols(Locale.ITALIAN).getWeekdays();
Calendar c = Calendar.getInstance();
Date date = new Date();
c.setTime(date);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
System.out.println(dayOfWeek);
System.out.println(weekdays[dayOfWeek]);
If you do not want to use Calendar class at all you can use this
String weekday_name = new SimpleDateFormat("EEEE", Locale.ENGLISH).format(System.currentTimeMillis());
i.e., result is,
"Sunday"
Here is my simple approach to get Current day
public String getCurrentDay(){
String daysArray[] = {"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday", "Saturday"};
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
return daysArray[day];
}
you can use that code for Kotlin which you will use calendar class from java into Kotlin
val day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
fun dayOfWeek() {
println("What day is it today?")
val day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
println( when (day) {
1 -> "Sunday"
2 -> "Monday"
3 -> "Tuesday"
4 -> "Wednesday"
5 -> "Thursday"
6 -> "Friday"
7 -> "Saturday"
else -> "Time has stopped"
})
}
Using both method you find easy if you wont last seven days
you use (currentdaynumber+7-1)%7,(currentdaynumber+7-2)%7.....upto 6
public static String getDayName(int day){
switch(day){
case 0:
return "Sunday";
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
}
return "Worng Day";
}
public static String getCurrentDay(){
SimpleDateFormat dayFormat = new SimpleDateFormat("EEEE", Locale.US);
Calendar calendar = Calendar.getInstance();
return dayFormat.format(calendar.getTime());
}
Just in case you ever want to do this not on Android it's helpful to think about which day where as not all devices mark their calendar in local time.
From Java 8 onwards:
LocalDate.now(ZoneId.of("America/Detroit")).getDayOfWeek()
If you want to define the date string in strings.xml. You can do like below.
Calendar.DAY_OF_WEEK return value from 1 -> 7 <=> Calendar.SUNDAY -> Calendar.SATURDAY
strings.xml
<string-array name="title_day_of_week">
<item>日</item> <!-- sunday -->
<item>月</item> <!-- monday -->
<item>火</item>
<item>水</item>
<item>木</item>
<item>金</item>
<item>土</item> <!-- saturday -->
</string-array>
DateExtension.kt
fun String.getDayOfWeek(context: Context, format: String): String {
val date = SimpleDateFormat(format, Locale.getDefault()).parse(this)
return date?.getDayOfWeek(context) ?: "unknown"
}
fun Date.getDayOfWeek(context: Context): String {
val c = Calendar.getInstance().apply { time = this#getDayOfWeek }
return context.resources.getStringArray(R.array.title_day_of_week)[c[Calendar.DAY_OF_WEEK] - 1]
}
Using
// get current day
val currentDay = Date().getDayOfWeek(context)
// get specific day
val dayString = "2021-1-4"
val day = dayString.getDayOfWeek(context, "yyyy-MM-dd")
As DAY_OF_WEEK in GregorianCalender class is a static field you can access it directly
as foolows
int dayOfWeek = GregorianCalender.DAY_OF_WEEK;