Have you considered using the new date/time API? The old classes (Date
, Calendar
and SimpleDateFormat
) have lots of problems and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time
and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp
), but the classes and methods names are the same.
First, you need to create a DateTimeFormatter
to match the format 14 Jun, Wed
. So, we need to create a formatter with this pattern (day/month/weekday). As the month name and weekday are in English, we use java.util.Locale
class to make sure it works even if your system's default locale is not English.
There's another problem: in this format (14 Jun, Wed
), there's no year. So we have 2 alternatives:
- Assume the current year
- Search for a year that matches the day/month/weekday: I'm considering that, if the input is, for example,
14 Jun, Tue
, we need to find a year where "14 Jun" is a Tuesday (so, we can't assume it's always the current year).
I'm writing the code for both. In this parsing, I'm using the LocalDate
class, as it seems to be the best choice for your case (this class represents a date with day, month and year):
String input = "14 Jun, Wed";
// alternative 1: formatter assuming it's always the current year
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder()
// pattern matching day/month/weekday
.appendPattern("dd MMM, EEE")
// assume current year as default
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
// use English locale (to make sure month and weekday are parsed correctly)
.toFormatter(Locale.ENGLISH);
LocalDate dt = LocalDate.parse(input, formatter1);
System.out.println(dt); // 2017-06-14
// alternative 2: parse day and month, find a year that matches the weekday
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("dd MMM, EEE", Locale.ENGLISH);
// get parsed object (think of this as an intermediary object that contains all the parsed fields)
TemporalAccessor parsed = formatter2.parse(input);
// get the current year
int year = Year.now().getValue();
// get the parsed weekday (Wednesday)
DayOfWeek weekday = DayOfWeek.from(parsed);
// try a date with the parsed day and month, at this year
MonthDay monthDay = MonthDay.from(parsed);
dt = monthDay.atYear(year);
// find a year that matches the day/month and weekday
while (dt.getDayOfWeek() != weekday) {
// I'm going to previous year, but you can choose to go to the next (year++) if you want
year--;
dt = monthDay.atYear(year);
}
System.out.println(dt); // 2017-06-14
The output for both is:
2017-06-14
Note that, if the input is 14 Jun, Tue
, alternative 1 will throw an Exception (because the weekday does't match the current year) and alternative 2 (code inspired (not to say copied) by this answer) will look for a year that matches the weekday (in this case, it will find 2016-06-14
).
As it's not clear what alternative you want, just choose one according to your use cases.
The output format (2017-06-14
) is the result of LocalDate.toString()
. If you want to change it, just create another formatter:
// create formatter with another format for output
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
System.out.println(outputFormatter.format(dt)); // 14/06/2017
For the example above, the output is:
14/06/2017
You can check the javadoc for more details about the available formats.