This repository has been archived by the owner on Jul 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add strptime and strftime to datetime classes (#101)
- strftime and strptime easily map to DateTimeFormatterBuilder, although with a different syntax. - strftime and strptime are implementation dependent, yielding different results on different operating systems and locale definitions. - The JVM locale is set to the Python's locale on startup
- Loading branch information
1 parent
e6bb0f7
commit 81bbd40
Showing
9 changed files
with
370 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
...eter/src/main/java/ai/timefold/jpyinterpreter/types/datetime/PythonDateTimeFormatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package ai.timefold.jpyinterpreter.types.datetime; | ||
|
||
import java.time.DayOfWeek; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.format.DateTimeFormatterBuilder; | ||
import java.time.format.FormatStyle; | ||
import java.time.format.TextStyle; | ||
import java.time.temporal.ChronoField; | ||
import java.time.temporal.WeekFields; | ||
import java.util.regex.Pattern; | ||
|
||
import ai.timefold.jpyinterpreter.types.errors.ValueError; | ||
|
||
/** | ||
* Based on the format specified | ||
* <a href="https://docs.python.org/3.11/library/datetime.html#strftime-and-strptime-format-codes">in | ||
* the datetime documentation</a>. | ||
*/ | ||
public class PythonDateTimeFormatter { | ||
private final static Pattern DIRECTIVE_PATTERN = Pattern.compile("([^%]*)%(.)"); | ||
|
||
static DateTimeFormatter getDateTimeFormatter(String pattern) { | ||
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); | ||
var matcher = DIRECTIVE_PATTERN.matcher(pattern); | ||
int endIndex = 0; | ||
while (matcher.find()) { | ||
var literalPart = matcher.group(1); | ||
builder.appendLiteral(literalPart); | ||
endIndex = matcher.end(); | ||
|
||
char directive = matcher.group(2).charAt(0); | ||
switch (directive) { | ||
case 'a' -> { | ||
builder.appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT); | ||
} | ||
case 'A' -> { | ||
builder.appendText(ChronoField.DAY_OF_WEEK, TextStyle.FULL); | ||
} | ||
case 'w' -> { | ||
builder.appendValue(ChronoField.DAY_OF_WEEK); | ||
} | ||
case 'd' -> { | ||
builder.appendValue(ChronoField.DAY_OF_MONTH, 2); | ||
} | ||
case 'b' -> { | ||
builder.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT); | ||
} | ||
case 'B' -> { | ||
builder.appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL); | ||
} | ||
case 'm' -> { | ||
builder.appendValue(ChronoField.MONTH_OF_YEAR, 2); | ||
} | ||
case 'y' -> { | ||
builder.appendPattern("uu"); | ||
} | ||
case 'Y' -> { | ||
builder.appendValue(ChronoField.YEAR); | ||
} | ||
case 'H' -> { | ||
builder.appendValue(ChronoField.HOUR_OF_DAY, 2); | ||
} | ||
case 'I' -> { | ||
builder.appendValue(ChronoField.HOUR_OF_AMPM, 2); | ||
} | ||
case 'p' -> { | ||
builder.appendText(ChronoField.AMPM_OF_DAY); | ||
} | ||
case 'M' -> { | ||
builder.appendValue(ChronoField.MINUTE_OF_HOUR, 2); | ||
} | ||
case 'S' -> { | ||
builder.appendValue(ChronoField.SECOND_OF_MINUTE, 2); | ||
} | ||
case 'f' -> { | ||
builder.appendValue(ChronoField.MICRO_OF_SECOND, 6); | ||
} | ||
case 'z' -> { | ||
builder.appendOffset("+HHmmss", ""); | ||
} | ||
case 'Z' -> { | ||
builder.appendZoneOrOffsetId(); | ||
} | ||
case 'j' -> { | ||
builder.appendValue(ChronoField.DAY_OF_YEAR, 3); | ||
} | ||
case 'U' -> { | ||
builder.appendValue(WeekFields.of(DayOfWeek.SUNDAY, 7).weekOfYear(), 2); | ||
} | ||
case 'W' -> { | ||
builder.appendValue(WeekFields.of(DayOfWeek.MONDAY, 7).weekOfYear(), 2); | ||
} | ||
case 'c' -> { | ||
builder.appendLocalized(FormatStyle.MEDIUM, FormatStyle.MEDIUM); | ||
} | ||
case 'x' -> { | ||
builder.appendLocalized(FormatStyle.MEDIUM, null); | ||
} | ||
case 'X' -> { | ||
builder.appendLocalized(null, FormatStyle.MEDIUM); | ||
} | ||
case '%' -> { | ||
builder.appendLiteral("%"); | ||
} | ||
case 'G' -> { | ||
builder.appendValue(WeekFields.of(DayOfWeek.MONDAY, 4).weekBasedYear()); | ||
} | ||
case 'u' -> { | ||
builder.appendValue(WeekFields.of(DayOfWeek.MONDAY, 4).dayOfWeek(), 1); | ||
} | ||
case 'V' -> { | ||
builder.appendValue(WeekFields.of(DayOfWeek.MONDAY, 4).weekOfYear(), 2); | ||
} | ||
default -> { | ||
throw new ValueError("Invalid directive (" + directive + ") in format string (" + pattern + ")."); | ||
} | ||
} | ||
} | ||
builder.appendLiteral(pattern.substring(endIndex)); | ||
return builder.toFormatter(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.