I want to get the day (e.g. 1st Sunday, 2nd Tuesday) of this month as Calendar. How can I achieve this with class Calendar in Android? Thanks.
-
What have you tried so far ? – twenk11k Jun 04 '19 at 06:23
-
You can use java.text.SimpleDateFormat to get the format – Rahul Khurana Jun 04 '19 at 06:43
-
1See this https://stackoverflow.com/questions/39528331/get-third-friday-of-a-month – Naitik Soni Jun 04 '19 at 10:27
-
@RahulKhurana `SimpleDateFormat` is notoriously troublesome and long outdated. And while it can give you `1 Sunday` and `2 Tuesday`, I don’t think it can give you `1st Sunday` and `2nd Tuesday` with the ordinal indicators. – Ole V.V. Jun 05 '19 at 08:13
1 Answers
java.time and ThreeTenABP
Edit: The elegant solution uses a DateTimeFormatter
:
Locale language = Locale.ENGLISH;
Map<Long, String> ordinalNumber = new HashMap<>(8);
ordinalNumber.put(1L, "1st");
ordinalNumber.put(2L, "2nd");
ordinalNumber.put(3L, "3rd");
ordinalNumber.put(4L, "4th");
ordinalNumber.put(5L, "5th");
DateTimeFormatter dayFormatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.ALIGNED_WEEK_OF_MONTH, ordinalNumber)
.appendPattern(" EEEE 'of the month'")
.toFormatter(language);
LocalDate date = LocalDate.now(ZoneId.of("Pacific/Auckland"));
String dayString = date.format(dayFormatter);
System.out.println("" + date + " is the " + dayString);
When I ran this snippet just now, it output:
2019-06-05 is the 1st Wednesday of the month
Obviously you can put in any date you wish other than today’s date in New Zealand.
The concept of aligned week of month defines the first week of the month as days 1 through 7, the 2nd week is 8 through 14, etc. So when a Wednesday is in week 1 according to this scheme, we also know that it must be the 1st Wednesday of the month. Same argument for other numbers.
I am not using the Calendar
class you mentioned since it is poorly designed and long outdated. Instead I am using java.time, the modern Java date and time API.
Original code (a bit shorter, but nevertheless does a little more hand work):
String[] ordinalNumber = { "0th", "1st", "2nd", "3rd", "4th", "5th" };
LocalDate date = LocalDate.now(ZoneId.of("Pacific/Auckland"));
DayOfWeek day = date.getDayOfWeek();
int numberDowOfMonth = date.get(ChronoField.ALIGNED_WEEK_OF_MONTH);
String dayString = String.format(language, "%s %s of the month",
ordinalNumber[numberDowOfMonth],
day.getDisplayName(TextStyle.FULL_STANDALONE, language));
System.out.println("" + date + " is the " + dayString);
Output is the same as above.
There’s an unused 0th element of my ordinalNumber
array. I only put it there because arrays are 0-based in Java and I wanted the other strings to be aligned with the numbers.
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.

- 81,772
- 15
- 137
- 161