I am trying to compare these two dates :
17 Oct. 2019 (08:23)
19 déc. 2019 (21:15)
The months are in French and the main problem is the months. Do I need to put an if statement for every type of month so I can switch it with the appropriate month? For example:
if (MonthValue.equals("oct."){
DateValue.replace("oct.","10");
}
Or is there an easier solution, because I need to check in a table if the first value is bigger than the second one.
Edit :
My new Code :
String target1 = "17 oct. 2019 (08:23)";
String target2 = "19 déc. 2019 (21:15)";
DateFormat df = new SimpleDateFormat("dd MMM. YYYY (kk:mm)", Locale.FRENCH);
Date result = df.parse(target1);
Date result2 = df.parse(target2);
System.out.println(result);
System.out.println(result2);
if(result.compareTo(result2) < 0) {
System.out.println("true");
}
else {
System.out.println("false");
}
Doesn't work gives this error:
java.text.ParseException: Unparseable date: "17 oct. 2019 (08:23)"
java.time and optional parts in the format pattern string
Like the others I recommend that you use java.time, the modern Java date and time API, for your date and time work. I understand that if your month names are five letters or shorter (for example avril), they are written out in full, whereas if they are seven letters or longer (for example juillet), they are abbreviated. The following formatter can parse in both situations:
private static final DateTimeFormatter DATE_FORMATTER
= new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd [MMMM][MMM] uuuu (HH:mm)")
.toFormatter(Locale.FRENCH);
Square brackets [] in the format pattern string surround optional parts. MMMM is for full month name. MMM is for the abbreviation. So the point in [MMMM][MMM] is that it will successfully parse either full month name or abbreviations and just skip the one that doesn’t work. Since you gave an example of Oct. being written with an upper case O, I have also specified that the parsing should not be sensitive to case. If this is not necessary, you may use this simpler formatter:
private static final DateTimeFormatter DATE_FORMATTER
= DateTimeFormatter.ofPattern("dd [MMMM][MMM] uuuu (HH:mm)", Locale.FRENCH);
In order to check that all months work, I have set up these test data:
String[] dateStrings = {
"17 Oct. 2019 (08:23)",
"19 déc. 2019 (21:15)",
"01 avril 2021 (09:40)",
"08 janv. 2020 (01:18)",
"28 févr. 2021 (21:41)",
"03 mars 2020 (22:54)",
"06 mai 2020 (03:14)",
"21 juin 2020 (07:15)",
"18 juil. 2020 (23:06)",
"06 août 2020 (22:28)",
"29 sept. 2020 (06:04)",
"18 nov. 2019 (01:35)"
};
To parse and compare two of them use LocalDateTime.parse() and .isBefore():
LocalDateTime dateTime1 = LocalDateTime.parse(dateStrings[1], DATE_FORMATTER);
LocalDateTime dateTime2 = LocalDateTime.parse(dateStrings[2], DATE_FORMATTER);
if (dateTime1.isBefore(dateTime2)) {
System.out.format(Locale.FRENCH, "%s is before %s%n", dateTime1, dateTime2);
}
Output:
2019-12-19T21:15 is before 2021-04-01T09:40
For comparison you may also exploit the fact that LocalDateTime implements Comparable. This is practical when sorting the dates and times, for example. As a brief example let’s sort all the LocalDateTime objects that come out of parsing the above strings:
Arrays.stream(dateStrings)
.map(ds -> LocalDateTime.parse(ds, DATE_FORMATTER))
.sorted()
.forEach(System.out::println);
2019-10-17T08:23
2019-11-18T01:35
2019-12-19T21:15
2020-01-08T01:18
2020-03-03T22:54
2020-05-06T03:14
2020-06-21T07:15
2020-07-18T23:06
2020-08-06T22:28
2020-09-29T06:04
2021-02-28T21:41
2021-04-01T09:40
Link: Trail: Date Time (The Java™ Tutorials) explaining how to use java.time.
Using DateTimeFormatter with pattern dd MMM yyyy (HH:mm) to parse the date string like this
String target1 = "17 oct. 2019 (08:23)";
String target2 = "19 déc. 2019 (21:15)";
Locale locale = Locale.FRANCE;
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder().appendPattern("dd MMM yyyy (HH:mm)")
.toFormatter(locale);
LocalDateTime dateTime1 = LocalDateTime.parse(target1, dateTimeFormatter);
LocalDateTime dateTime2 = LocalDateTime.parse(target2, dateTimeFormatter);
System.out.println(dateTime1);
System.out.println(dateTime2);
if (dateTime1.compareTo(dateTime2) < 0) {
System.out.println("true");
} else {
System.out.println("false");
}
My recommendation:
parse the dates e.g. with a DateTimeFormatter to e.g. a LocalDateTime
compare the parsed dates (most date and time objects implement https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Comparable.html)
What I've got from your question is that you want to convert Month's names to their respective numbers. If this is the case, then you should try switch
Example:
switch (MonthValue){
case jan:
MonthValue = 1; // Set Month variable to it Numbered Position (type casting might be required)
break;
case feb:
MonthValue = 2;
break;
default:
System.out.println("Somthing...");
}
Try encoding to UTF8, which will avoid DateTimeParseException
Exception in thread "main" java.time.format.DateTimeParseException: Text '19 d??c. 2019 (21:15)' could not be parsed at index 3
public static void main(String args[]) throws Exception {
String date1 = "17 oct. 2019 (08:23)";
String date2 = "19 déc. 2019 (21:15)";
DateTimeFormatter longDateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy (HH:mm)").withLocale(Locale.FRENCH);
LocalDateTime lclDate1 = LocalDateTime.parse(encodeUTF8(date1), longDateTimeFormatter);
LocalDateTime lclDate2 = LocalDateTime.parse(encodeUTF8(date2), longDateTimeFormatter);
if (lclDate1.compareTo(lclDate2) < 0) {
System.out.println("true");
}
else {
System.out.println("false");
}
}
public static String encodeUTF8(String dateStr) {
byte[] bytes = dateStr.getBytes();
String utf8EncodStr = new String(bytes, StandardCharsets.UTF_8);
return utf8EncodStr;
}
Related
I need a different format of strings to convert to "DD.MM.YYYY".
"Thu, 3 Nov 2022 06:00:00 +0100" has to be changed to "03.11.2022"
and
"01.11.2022 20:00:00" to "01.11.2022".
All the formats are in String.
I tried doing
String pattern="DD.MM.YYYY";
DateTimeFormatter formatter=DateTimeFormatter.ofPattern(pattern);
new SimpleDateFormat(pattern).parse("01.11.2022 20:00:00")
I have also tried doing the following
java.time.LocalDateTime.parse(
item.getStartdatum(),
DateTimeFormatter.ofPattern( "DDMMYYYY" )
).format(
DateTimeFormatter.ofPattern("DD.MM.YYYY")
)
But got the error :
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Sun, 30 Oct 2022 00:30:00 +0200' could not be parsed at index 0
I tried doing the following as well
String pattern="DD.MM.YYYY";
DateFormat format = new SimpleDateFormat(pattern);
Date date = format.parse(01.11.2022 20:00:00);
However, I am not getting the correct output. How can I get my desired result?
Several things…
if you can use java.time, use it exclusively if possible (no SimpleDateFormat or similar legacy stuff)
a DateTimeFormatter can be used to parse and format Strings representing a datetime, if input and output format are different, you will need two different DateTimeFormatters
the Text 'Sun, 30 Oct 2022 00:30:00 +0200' could not be parsed at index 0 due to your try to parse it with the pattern "DD.MM.YYYY", which is wrong on several levels:
the pattern seems to expect the String to start with a numerical representation of the day of month, but it starts with Thu, an abbreviation of the name of a day of week
the symbol D means day of year, a number between 1 and 366 (in leap years, 365 otherwise)
the symbol Y means week-based year
Read more about those symbols in the JavaDocs of DateTimeFormatter
You could do the following instead:
public static void main(String[] args) {
// two example inputs
String first = "Thu, 3 Nov 2022 06:00:00 +0100";
String second = "01.11.2022 20:00:00";
// prepare a formatter for each pattern in order to parse the Strings
DateTimeFormatter dtfInFirst = DateTimeFormatter.ofPattern(
"EEE, d MMM uuuu HH:mm:ss x",
Locale.ENGLISH
);
// (second one does not have an offset from UTC, so the resulting class is different)
DateTimeFormatter dtfInSecond = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss");
// parse the Strings using the formatters
OffsetDateTime odt = OffsetDateTime.parse(first, dtfInFirst);
LocalDateTime ldt = LocalDateTime.parse(second, dtfInSecond);
// prepare a formatter, this time for output formatting
DateTimeFormatter dtfDateOnlySeparatedByDots = DateTimeFormatter.ofPattern("dd.MM.uuuu");
// extract the date part of each result of the parsing
LocalDate firstResult = odt.toLocalDate();
LocalDate secondResult = ldt.toLocalDate();
// and print it formatted using the output formatter
System.out.println(first + " ---> "
+ firstResult.format(dtfDateOnlySeparatedByDots));
System.out.println(second + " ---> "
+ secondResult.format(dtfDateOnlySeparatedByDots));
}
Which will output the conversion results as follows:
Thu, 3 Nov 2022 06:00:00 +0100 ---> 03.11.2022
01.11.2022 20:00:00 ---> 01.11.2022
The first formatter will need a Locale because of the presence of names (day of week & month). You cannot parse that using any exclusively numerical parser and the language / culture must match.<
short version
public static void main(String[] args) {
// two example inputs
String first = "Thu, 3 Nov 2022 06:00:00 +0100";
String second = "01.11.2022 20:00:00";
// prepare a custom formatter for the second pattern
DateTimeFormatter dtfInSecond = DateTimeFormatter
.ofPattern("dd.MM.uuuu HH:mm:ss");
// parse the first String by means of a built-in RFC formatter
OffsetDateTime odt = OffsetDateTime.parse(
first,
DateTimeFormatter.RFC_1123_DATE_TIME);
// parse the second String using the custom formatter
LocalDateTime ldt = LocalDateTime.parse(second, dtfInSecond);
// prepare a formatter, this time for output formatting
DateTimeFormatter dtfDateOnlySeparatedByDots = DateTimeFormatter
.ofPattern("dd.MM.uuuu");
// and print it formatted using the output formatter
System.out.println(first + " ---> "
+ odt.format(dtfDateOnlySeparatedByDots));
System.out.println(second + " ---> "
+ ldt.format(dtfDateOnlySeparatedByDots));
}
HINT:
For dates like the one mentioned in your comment…
Text '9.28.2022 6:30:00' could not be parsed at index 0
you will have to use a pattern with single-digit day of month and hour of day, probably even month of year if anything like 9.8.2022 is possible. However, you will definitely need to switch day of month and month of year because there is just no month no. 28 in a year.
Short example:
String third = "9.28.2022 6:30:00";
DateTimeFormatter dtfInThird = DateTimeFormatter
.ofPattern("M.d.uuuu H:mm:ss");
LocalDateTime ldtThird = LocalDateTime.parse(third, dtfInThird);
System.out.println(third + " ---> "
+ ldtThird.format(dtfDateOnlySeparatedByDots));
Executed in a main, this will output
9.28.2022 6:30:00 ---> 28.09.2022
The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
deHaar has already written a good answer. However, if you want to use a single DateTimeFormatter, you can check this answer.
For parsing, you can build a DateTimeFormatter with optional patterns and default time-zone offset value (since you do not have time-zone offset in the second date-time string) as follows:
DateTimeFormatter parser = new DateTimeFormatterBuilder()
.appendPattern("[d.M.uuuu H:m:s][EEE, d MMM uuuu H:m:s X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter(Locale.ENGLISH);
where the optional patterns are in square brackets. Alternatively, you can use DateTimeFormatterBuilder#optionalStart and DateTimeFormatterBuilder#optionalEnd to specify optional patterns.
With this parser, you can parse the given date-time strings to OffsetDateTime and format it to the desired string using the following DateTimeFormatter:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu", Locale.ENGLISH);
Demo:
public class Main {
public static void main(String[] args) {
DateTimeFormatter parser = new DateTimeFormatterBuilder()
.appendPattern("[d.M.uuuu H:m:s][EEE, d MMM uuuu H:m:s X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter(Locale.ENGLISH);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu", Locale.ENGLISH);
// Test
Stream.of(
"Thu, 3 Nov 2022 06:00:00 +0100",
"01.11.2022 20:00:00"
)
.map(s -> OffsetDateTime.parse(s, parser).format(formatter).toString())
.forEach(System.out::println);
;
}
}
Output:
03.11.2022
01.11.2022
Note
Make sure to check the DateTimeFormatter documentation to understand the difference between Y and y and between D and d.
You can use y instead of u but I prefer u to y with DateTimeFormatter.
Learn more about the modern Date-Time API from Trail: Date Time.
I would like to parse an GMT-date like Wed, 21 Oct 2016 07:28:00 GMTwith DateTimeFormatter into an Instant. To create the pattern i used the official documentation: DateTimeFormatter
My code so far:
String date = "Wed, 21 Oct 2016 07:28:00 GMT";
DateTimeFormatter gmtFormat = DateTimeFormatter.ofPattern("EEE' dd LLL yyyy HH:mm:ss '''");
TemporalAccessor parsed = gmtFormat.parse(date);
Instant a = Instant.from(parsed);
System.out.println(a);
But every time i've got this error:
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Wed, 21 Oct 2016 07:28:00 GMT' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777)
At index 0 is Wed, I used EEE which represents day-of-week by definition, there are also examples which represent: Tue; Tuesday; T.
I've also tried lower-, and uppercase but not successfully. What is wrong? Did I overlook something?
It works with the code
String date = "Fri, 21 Oct 2016 07:28:00 GMT";
DateTimeFormatter gmtFormat = DateTimeFormatter.RFC_1123_DATE_TIME;
TemporalAccessor parsed = gmtFormat.parse(date);
Instant a = Instant.from(parsed);
System.out.println(a);
But you have to change the day because otherwise it doesn't fit to the given date.
EEE is the proper format for Wed. But it does not include the comma.
Try this:
DateTimeFormatter gmtFormat = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss '''");
Useful link
You're asking for redundant information: The day of the week and the date.
Change the format to just ignore the first three characters, leaving it reading the day/month/year.
How can we remove and preserve only Date from a String:
For ex: String outPut = {Time = 0:0:0} {Timestamp = Tue Oct 20 23:54:10 BST 2013}
I would like to have only Date
For ex: Tue Oct 20 2013
So far, I have tried the following approach:
String[] manipulateDate = output.getDate().split("\\{");
for(String s : manipulateDate ){
String outputDate = manipulateDate [2].replaceAll("\\}", "").replaceAll("\\s*\\bTimestamp =\\b\\s*","");
System.out.println(outputDate );
}
What is the best way to implement and use Java Date/String?
To strictly answer your question, you could do:
String date = output.replaceAll(".*Timestamp = (.*)? \\d{2}:.*?(\\d{4}).*", "$1 $2");
But it may be preferable to parse the whole string as a date object:
String output = "{Time = 0:0:0} {Timestamp = Sun Oct 20 23:54:10 BST 2013}";
String timestamp = output.replaceAll("\\{.*?\\} \\{Timestamp = (.*)\\}", "$1"); //Sun Oct 20 23:54:10 BST 2013
ZonedDateTime dateTime = ZonedDateTime.parse(timestamp, DateTimeFormatter.ofPattern("E MMM dd HH:mm:ss z yyyy", Locale.ENGLISH));
From that point on, you can do what you want with the date object, including printing it as a string. Note that I changed the original string to Sunday (vs. Tuesday in your question): parsing it as a date also caught the fact that the 20th of October 2013 was not a Thursday, another advantage over strings.
I have an array of Strings with the dates e.g.:
Tue, 09 Feb 2016 14:07:00 GMT;
Tue, 09 Feb 2016 19:55:00 GMT.
Now I want to find the most recent date on this list. In order to do that, I try to deserialize these strings to java.util.Date objects and after that compare them.
The code sample of java.util.Date object generation:
strDate = "Tue, 09 Feb 2016 14:07:00 GMT";
DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
Date date;
try {
date = format.parse(strDate);
//Result: Tue Feb 09 16:07:00 IST 2016
System.out.println("Result: " + date.toString());
} catch(ParseException e) {
e.printStackTrace();
}
My questions:
Why is the result in IST 2016 time zone and not in GMT? What does the IST 2016 stand for? Is it India Standard Time or Irish Standard Time or Israel Standard Time?
The initial string is in EEE, dd MMM format, the SimpleDateFormat pattern is also in this format, thus, why the result is in EEE, MMM dd format?
How can get a java.util.Date object in the same timezone as the initial string, in my case — GMT?
Is the approach I'm using to find the most recent date in the list is OK or there is more convenient/modern way to do that in Java 8, e.g., with the usage of LocalDateTime?
You are relying to Date.toString() to print your date when you should format it to a String with a formatter. What you are seeing is just the default pattern of Date.toString(). What you must keep in mind is that a Date does not have a timezone. You are seeing the output with the IST timezone, this must be because the current locale for the JVM is set to some specific locale for which the timezone name is "IST".
With regard to your point 4, yes, you can do it much cleaner with Java Time API introduced in Java 8. You can create a List of your strings to parse, create a DateTimeFormatter to parse it, and keep the maximum date value.
public static void main(String[] args) {
List<String> dates = Arrays.asList("Tue, 09 Feb 2016 14:07:00 GMT", "Tue, 09 Feb 2016 19:55:00 GMT");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime maxDate = dates.stream()
.map(s -> ZonedDateTime.parse(s, formatter))
.max(ZonedDateTime::compareTo)
.get(); // or .orElse(null)
System.out.println(maxDate);
}
This code is using a ZonedDateTime to keep the time-zone of the incoming strings.
Your computer seems to be set to IST. To force GMT output, import java.util.TimeZone and do this in your try block:
format.setTimeZone(TimeZone.getTimeZone("GMT"));
date = format.parse(strDate);
System.out.println("Result: " + format.format(date));
I need to parse the dates of the format "January 10th, 2010" in Java. How can I do this?
How to handle the ordinal indicators, the st, nd, rd, or th trailing the day number?
This works:
String s = "January 10th, 2010";
DateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy");
System.out.println("" + dateFormat.parse(s.replaceAll("(?:st|nd|rd|th),", "")));
but you need to make sure you are using the right Locale to properly parse the month name.
I know you can include general texts inside the SimpleDateFormat pattern. However in this case the text is dependent on the info and is actually not relevant to the parsing process.
This is actually the simplest solution I can think of. But I would love to be shown wrong.
You can avoid the pitfalls exposed in one of the comments by doing something similar to this:
String s = "January 10th, 2010";
DateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy");
System.out.println("" + dateFormat.parse(s.replaceAll("(?<= \\d+)(?:st|nd|rd|th),(?= \\d+$)", "")));
This will allow you to not match Jath,uary 10 2010 for example.
I should like to contribute the modern answer. Rather than the SimpleDateFormat class used in the two top-voted answer today you should use java.time, the modern Java date and time API. It offers a couple of nice solutions.
Easy solution
We first define a formatter for parsing:
private static final DateTimeFormatter PARSING_FORMATTER = DateTimeFormatter.ofPattern(
"MMMM d['st']['nd']['rd']['th'], uuuu", Locale.ENGLISH);
Then we use it like this:
String dateString = "January 10th, 2010";
LocalDate date = LocalDate.parse(dateString, PARSING_FORMATTER);
System.out.println("Parsed date: " + date);
Output is:
Parsed date: 2010-01-10
The square brackets [] in the format pattern string enclose optional parts, and the single quotes enclose literal text. So d['st']['nd']['rd']['th'] means that there may be st, nd, rd and/or th after the day of month.
More solid solution
A couple of limitations with the approach above are
It accepts any ordinal indicator, for example 10st and even 10stndrdth.
While the formatter works for parsing, you cannot use it for formatting (it would give January 10stndrdth, 2010).
If you want better validation of the ordinal indicator or you want the possibility of formatting the date back into a string, you may build your formatter in this way:
private static final DateTimeFormatter FORMATTING_AND_PARSING_FORMATTER;
static {
Map<Long, String> ordinalNumbers = new HashMap<>(42);
ordinalNumbers.put(1L, "1st");
ordinalNumbers.put(2L, "2nd");
ordinalNumbers.put(3L, "3rd");
ordinalNumbers.put(21L, "21st");
ordinalNumbers.put(22L, "22nd");
ordinalNumbers.put(23L, "23rd");
ordinalNumbers.put(31L, "31st");
for (long d = 1; d <= 31; d++) {
ordinalNumbers.putIfAbsent(d, "" + d + "th");
}
FORMATTING_AND_PARSING_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("MMMM ")
.appendText(ChronoField.DAY_OF_MONTH, ordinalNumbers)
.appendPattern(", uuuu")
.toFormatter(Locale.ENGLISH);
}
This will parse the date string the same as the one above. Let’s also try it for formatting:
System.out.println("Formatted back using the same formatter: "
+ date.format(FORMATTING_AND_PARSING_FORMATTER));
Formatted back using the same formatter: January 10th, 2010
Links
Oracle tutorial: Date Time explaining how to use java.time.
My answer to a question about formatting ordinal indicators from which I took the more solid formatter.
You can set nd etc as literals in a SimpleDateFormat. You can define the four needed format and try them. Starting with th first, because I guess this will occur more often. If it fails with ParseException, try the next one. If all fail, throw the ParseException. The code here is just a concept. In real-life you may would not generate the formats new everytime and may think about thread-safety.
public static Date hoolaHoop(final String dateText) throws ParseException
{
ParseException pe=null;
String[] sss={"th","nd","rd","st"};
for (String special:sss)
{
SimpleDateFormat sdf=new SimpleDateFormat("MMMM d'"+special+",' yyyy");
try{
return sdf.parse(dateText);
}
catch (ParseException e)
{
// remember for throwing later
pe=e;
}
}
throw pe;
}
public static void main (String[] args) throws java.lang.Exception
{
String[] dateText={"January 10th, 2010","January 1st, 2010","January 2nd, 2010",""};
for (String dt:dateText) {System.out.println(hoolaHoop(dt))};
}
Output:
Sun Jan 10 00:00:00 GMT 2010
Fri Jan 01 00:00:00 GMT 2010
Sat Jan 02 00:00:00 GMT 2010
Exception in thread "main" java.text.ParseException: Unparseable date: ""
"th","nd","rd","st" is of course only suitable for Locales with english language. Keep that in mind. In france, "re","nd" etc I guess.
This is another easy way ,but need to include apache commons jar.
import org.apache.commons.lang.time.*;
String s = "January 10th, 2010";
String[] freakyFormat = {"MMM dd'st,' yyyy","MMM dd'nd,' yyyy","MMM dd'th,' yyyy","MMM dd'rd,' yyyy"};
DateUtils du = new DateUtils();
System.out.println("" + du.parseDate(s,freakyFormat));