1

I'm trying to load from XML a schedule field which looks like this: "MON 17:20"

I want to avoid parse manually using string replace e.t.c. I checked online for this code

final String dateInString = "Mon, 05 May 1980";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.ENGLISH);
final LocalDate dateTime = LocalDate.parse(dateInString, formatter);

But it has no week field (I cannot retrieve the week). Is there any similar short parse system?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    what should be year and month ? – Amit Kumar Lal Apr 30 '20 at 21:06
  • 3
    What date should `MON 17:20` be parsed into? Which Monday? – Pshemo Apr 30 '20 at 21:12
  • My code basically schedule every X day of Week in that specific time. So my xml field goes like and repeat this every week. I don't need to parse month or year. So basically i do a split "," and parse all dates in that schedule to schedule which is the next available. – KbantikiMixaniki Apr 30 '20 at 21:41
  • @KbantikiMixaniki - Without year and month, it's **impossible** to calculate which week this `Mon` or `Tue` belong to. Do you mean starting from the current date? – Arvind Kumar Avinash Apr 30 '20 at 21:52
  • 1
    @KbantikiMixaniki [Have you read this answer?](https://stackoverflow.com/a/61533888/507738) What exactly do you want to do with the day-of-week and time? Do you want to combine it with a year and month, or perhaps a year and week number? – MC Emperor May 01 '20 at 09:33

4 Answers4

1

Try this.

final String dateInString = "Thu Apr 30, 2020 17:20";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd, yyyy HH:mm");
final LocalDateTime dateTime = LocalDateTime.parse(dateInString, formatter);
System.out.println(dateTime);

The above parses to this.

2020-04-30T17:20

If you want the week you can do this.

System.out.println(dateTime.get(ChronoField.ALIGNED_WEEK_OF_MONTH));
System.out.println(dateTime.get(ChronoField.ALIGNED_WEEK_OF_YEAR));

Prints

5
18

Updated Answer.

final String dateInString ="MON 17:20";
String[] vals = dateInString.split("\\s+");
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
final LocalTime dateTime = LocalTime.parse(vals[1], formatter);
System.out.println(vals[0] + " " + dateTime);

Prints

MON 17:20

Read the details at ChronoField
Check the java.time package for more on the Java Temporal capabilities.

WJS
  • 36,363
  • 4
  • 24
  • 39
  • Hello sir. Thank you for respond. I tried the following: final String dateInString = "Thu 17:20"; final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE HH:mm"); but it give error. I only need parse Day of Week and time but seems i can't right? – KbantikiMixaniki Apr 30 '20 at 21:38
  • So i don't have other option other than do it manually with splits and replace right? – KbantikiMixaniki Apr 30 '20 at 21:45
  • This is my code so far base on your example: https://pastebin.com/LySpaAQe You find it ok? Also i need make a static method to convert short week to int so i can add it in Calendar or there is also short way using libraries? Thanks – KbantikiMixaniki Apr 30 '20 at 23:18
1

Of course it's possible with the Java 8 Date & Time API.

You seem to have three fields: the day-of-week, the hour-of-day and the minute-of-hour. This could normally be parsed using DateTimeFormatter::ofPattern with the formatting string EEE HH:mm, but the problem is that MON (in all caps) is not standard; it should be Mon instead.

So we need to build our formatter using the DateTimeFormatterBuilder, instructing that the string should be parsed in a case-insensitive manner:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern("EEE HH:mm")
    .toFormatter(Locale.ROOT);

The only thing to do is parsing the fields using

TemporalAccessor parsed = formatter.parse(elem);

Now parsed contains the abovementioned parsed fields.

To a datetime

Of course, you don't have to convert this to an actual date. There are many use cases where one don't want a date, but rather only a day-of-week and the time. This is an example.

But if you, for example, want to get the current date and adjust it to match the data from your schedule, you can do something like this:

TemporalAdjuster adj = TemporalAdjusters.nextOrSame(DayOfWeek.of(parsed.get(ChronoField.DAY_OF_WEEK)));
LocalDateTime now = LocalDate.now()
    .atTime(LocalTime.from(parsed))
    .with(adj);
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
0

You need to pass your LocalDate object into the example shown here: Get Week Number of LocalDate (Java 8)

That should get it for you.

From the link above pass your 'dateTime' field in the code like...

    TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear(); 
int weekNumber = dateTime.get(woy);

Depending on your locale and where this code will run you might want to consider WeekFields.ISO as mentioned at the link above.

Waxhaw
  • 599
  • 5
  • 9
0

The problem isn’t that it’s difficult to parse using a DateTimeFormatter. The problem is that we haven’t got a good type to parse into. The information doesn’t fit in a LocalDate or LocalDateTime, for example. And depending on what you need for your scheduler I think that the solution is to parse into two objects instead of one: a day of week and a time of day.

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("EEE H:mm")
            .toFormatter(Locale.ENGLISH);

    String scheduleString = "MON 17:20";

    TemporalAccessor parsed = formatter.parse(scheduleString);
    DayOfWeek dow = DayOfWeek.from(parsed);
    LocalTime time = LocalTime.from(parsed);

    System.out.format("Schedule: every %s at %s", dow, time);

Output:

Schedule: every MONDAY at 17:20

Explicit use of the TemporalAccessor interface is considered low-level, but I much prefer this solution over String.replace() or String.split(). If you want to avoid the low-level interface, just parse the string twice, once into a DayOfWeek and once into a LocalTime.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161