Can anyone give me any examples of how to compare Dates using Spring Expression Languange (Spel)?
I have searched far and wide and nothing I find seems to fit my purpose. I'm using Java 8 and I have a response Object with a ZonedDateTime field which I somehow need to compare to a string in the form of YYYY-MM-DD -- IE: is before, is after, is equal, etc.
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
HashMap<String, Object> testHash = new HashMap<>();
testHash.put("dateField", zonedDateTime);
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariables(testHash);
Expression expression = parser.parseExpression("#dateField > '2016-01-01'");
The above is obviously not working. Anyone able to show me an example that does?
Below is the code for date comparison using Java 8 java.time package and Spring Expression Language. Hope this helps.
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import junit.framework.Assert;
public class TestDateSPEL {
#Test
public void testCompareDate() throws Exception {
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
String otherDate = "2010-12-25 12:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneId.systemDefault());
ZonedDateTime zdtOtherDate = ZonedDateTime.parse(otherDate, formatter);
//SpEL Context
EvaluationContext context = new StandardEvaluationContext(new ZonedDateTimeUtil());
context.setVariable("dateOne", zonedDateTime);
context.setVariable("dateTwo", zdtOtherDate);
//SpEL Parser
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("compareDate(#dateOne, #dateTwo)");
int value = (Integer) exp.getValue(context);
//"zonedDateTime" is after "zdtOtherDate"
Assert.assertEquals(1, value);
}
}
class ZonedDateTimeUtil {
public int compareDate(ZonedDateTime dateOne, ZonedDateTime dateTwo){
return dateOne.compareTo(dateTwo);
}
}
I would recommend to parse your String to Instant or ZoneDateTime or any TemporalAccessor and then use method compareTo() of interface ChronoZonedDateTime that is extended by TemporalAccessor to compare two dates. See javadoc for compareTo(). Use class java.time.format.DateTimeFormatter to parse a String to TemporalAccessor. (method parse()). Your code may look like:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
TemporalAccessor ta = dtf.parse(yourDateString);
boolean result = yourZonedDateTime.compareTo(ta);
That's a base to start with. Also you can see this article that explains how to parse a String of unknown format into date. It might be helpful.
Java 8 java.time package: parsing any string to date
Please try this as example I hope that it will help you....
DateFormat destDf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDate;
Date endDate;
String strDate1="2016-08-09 00:00:00";
String strDate2="2015-11-19 00:00:00";
startDate = destDf.parse(strDate1);
endDate = destDf.parse(strDate2);
if(startDate.after(endDate)){
Object Date;
if(startDate.before(endDate))
if(startDate.equals(endDate))
//You can check date in java like this also
Date Date date = new Date();
if(date.getDate()==startDate.getDate() && date.getMonth()==startDate.getMonth() && date.getYear()==startDate.getYear()){
System.out.println("Date1 is equal Date2");
}
Related
String date = "08/02/2022 Tuesday";
DateTimeFormatter LONG_DATE_FORMAT_ddMMyyyyEEEE = ofPattern("dd/MM/yyyy EEEE");
LocalDate.parse(date, LONG_DATE_FORMAT_ddMMyyyyEEEE);
I'm getting a DateTimeParseException with the following message: Text 08/02/2022 Tuesday' could not be parsed at index 11.
I suppose this is an issue with the EEEE side of my format, but I can't seem to understand what should replace it.
This is java 1.8.0_311
We need DateTimeFormatter class to format date string properly. We also need to convert the string date to LocalDate object and back to string again to display. The DateTimeParseException class handles any undesired outcomes.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
class Main {
public static void main(String[] args) {
try{
String date = "08-02-2022 Tuesday";
DateTimeFormatter pattern =
DateTimeFormatter.ofPattern("dd-MM-yyyy eeee");
// parsing string date to LocalDate obj
// The part you were missing
LocalDate formattedDate = LocalDate.parse(date, pattern);
// Again converting to string
System.out.println(formattedDate.format(pattern));
}
// handling exception for unparseble dates
catch(DateTimeParseException x){
System.out.println("The given date cannot be parsed");
}
}
}
LocalDate contains of a day, month, and year (Variation between +999999999-12-31 and -999999999-12-31)
Things like time and other values are rejected by the parsing. If you would like the day of the week, you can use a function like:
// Parses the date
LocalDate dt = LocalDate.parse("2018-11-27");
// Prints the day
System.out.println(dt.getDayOfWeek());
This works for me:
String date = "08/02/2022 Tuesday";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy EEEE");
LocalDate time = LocalDate.parse(date, formatter);
System.out.println(time.format(formatter));
private void showdataTable_btnActionPerformed(java.awt.event.ActionEvent evt) {
try {
DateFormat df = new SimpleDateFormat("YYYY-mm-dd'T'HH:MM:ss'Z'"); //set date format
String set = df.format(dateChoos1.getDate()); //add value to set
BasicDBObject whereQuery = new BasicDBObject();
whereQuery.put("datetimes", set); //where date via set(date)
DBCursor cursor = table.find(whereQuery);
while (cursor.hasNext()) {
DBObject obj = cursor.next();
String ip_address = (String) obj.get("ip_address");
String mac_address = (String) obj.get("mac_address");
Date datetimes = (Date) obj.get("datetimes");
String url = (String) obj.get("url");
model.insertRow(model.getRowCount(), new Object[]{datetimes, ip_address, mac_address, url});
}
} catch (Exception e) {
System.out.println("Something went wrong.");
}
}
Your format, YYYY-mm-dd'T'HH:MM:ss'Z' is not correct. Let's discuss everything which is wrong with this format.
You have used Y instead of y: The symbol Y is used for Week year while y is used for Year. Check Difference between year-of-era and week-based-year? to learn more about it.
You have used mm for month: The correct symbol for the month is M.
You have used MM for minutes: The correct symbol for the minute is m.
You have enclosed Z within single quotes: The symbol, Z is used for Time zone whereas 'Z' is nothing but a character literal. Probably you want to format the timezone offset of +00:00 as Z and for this, you should in fact use X.
So, the correct format is as follows:
yyyy-MM-dd'T'HH:mm:ssX
A demo with the suggested format:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.ENGLISH);
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
System.out.println(sdf.format(date));
}
}
Output:
2021-01-14T08:13:01Z
Note that the date-time API of java.util 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.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Use Date#toInstant to convert a java.util.Date object (the legacy type) to java.time.Instant (the modern type). Instant represents an instantaneous point on the time-line and should be just enough for most of your JSON operations. The Instant#toString returns the date-time string with UTC timezone offset which is compliant with ISO-8601 standards.
Demo:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
Instant instant = date.toInstant();
// Print the value of instant#toString
System.out.println(instant);
OffsetDateTime odt = instant.atOffset(ZoneOffset.UTC);
System.out.println(odt);
// Custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX", Locale.ENGLISH);
System.out.println(dtf.format(odt));
}
}
Output:
2021-01-14T08:28:35.659Z
2021-01-14T08:28:35.659Z
2021-01-14T08:28:35Z
I've got a Calendar Date in Java.
I need to convert it in a String with this format :
2020-12-29T00:00:00+01:00
How can I do it?
Thank you so much for your help.
Get the Date object by calling Calendar#getTime and format it using a SimpleDateFormat with the format, yyyy-MM-dd'T'HH:mm:ssXXX.
Note: Since the desired string has timezone offset of +01:00 hours, make sure you set the timezone of the SimpleDateFormat object to TimeZone.getTimeZone("GMT+1") before calling SimpleDateFormat#format.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
Date date = calendar.getTime();
String formatted = sdf.format(date);
System.out.println(formatted);
}
}
Another example:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String dateTimeString = "2020-12-29T00:00:00+01:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date obj = sdf.parse(dateTimeString);
Calendar calendar = Calendar.getInstance();
calendar.setTime(obj);
// Formatting this calendar object
Date date = calendar.getTime();
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
String formatted = sdf.format(date);
System.out.println(formatted);
}
}
Output:
2020-12-29T00:00:00+01:00
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work.
Here’s a formatter for your desired format:
private static final DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX");
With this we may do:
ZoneId zone = ZoneId.of("Asia/Barnaul");
ZonedDateTime dateTime
= LocalDate.of(2020, Month.DECEMBER, 29).atStartOfDay(zone);
String formatted = dateTime.format(formatter);
System.out.println(formatted);
Output from this example snipoet is:
2020-12-29T00:00:00+07:00
If you cannot avoid getting a Calendar
If you are getting a Calendar object from a legacy API that you cannot afford to upgrade to java.time just now, convert it to ZonedDateTime. It is almost certainly really a GregorianCalendar (or formatting into that format would not make much sense), which makes the conversion straightforward.
Calendar yourCalendar = getCalendarFromLegacyApi();
ZonedDateTime dateTime
= ((GregorianCalendar) yourCalendar).toZonedDateTime();
The rest is as before, as is the output.
If you need to take into account the possibility that the Calendar is not a GregorianCalendar, use this slightly more complicated conversion instead:
ZonedDateTime dateTime = yourCalendar.toInstant()
.atZone(yourCalendar.getTimeZone().toZoneId());
Link
Oracle tutorial: Date Time explaining how to use java.time.
This question already has answers here:
Parse CIM_DateTime with milliseconds to Java Date
(2 answers)
Closed 2 years ago.
Into a Java application I have this String representing a timestamp containing values like this: 2009-10-17 05:45:14.000
As you can see the string represents the year, the month, the day, the hour, the minute, the second and the millisencond.
I have to convert a String like this into a Date object (if possible bringing also the millisecond information, is it possible?)
How can I correctly implement it?
You can use SimpleDateFormat to parse a given string date according to a given pattern, it also supports milliseconds, like this:
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
Date date=format.parse("2009-10-17 05:45:14.050");
Since Java 8, you should use the classes in the date-time API
Class LocalDateTime stores a date and a time up to nanosecond precision.
Here is a snippet showing how to parse a string into an instance of LocalDateTime
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateTime {
public static void main(String[] args) {
String str = "2009-10-17 05:45:14.000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(str, formatter);
}
}
Using SimpleDateFormat, how can you parse the String: "2013-05-23T09:18:07 p.m..380+0000"
All my SimpleDateFormat Strings are tripping up on the "p.m." part.
Thanks in advance.
EDIT: We have no control over the format coming in.
I've tried:
"yyyy-MM-dd'T'HH:mm:ss a.a..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaaa.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m'..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m.'.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss a.'m..'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aa'm'..SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aa'm.'.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa'..'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa.'.'SSSZ"
"yyyy-MM-dd'T'HH:mm:ss aaa'.'.SSSZ"
It's not clear what the "380+0000" part is meant to be, but you can fix the AM/PM part, by setting the DateFormatSymbols for the SimpleDateFormat. Here's an example:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws Exception {
String text = "2013-05-23T09:18:07 p.m..380+0000";
String pattern = "yyyy-MM-dd'T'hh:mm:ss aa'.380+0000'";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
DateFormatSymbols symbols = format.getDateFormatSymbols();
symbols = (DateFormatSymbols) symbols.clone();
symbols.setAmPmStrings(new String[] { "a.m.", "p.m."});
format.setDateFormatSymbols(symbols);
Date date = format.parse(text);
System.out.println(date);
}
}
I don't know whether you have to clone the DateFormatSymbols before mutating it - it's not clear, to be honest... the documentation points two ways:
DateFormatSymbols objects are cloneable. When you obtain a DateFormatSymbols object, feel free to modify the date-time formatting data. For instance, you can replace the localized date-time format pattern characters with the ones that you feel easy to remember. Or you can change the representative cities to your favorite ones.
Given that it's mentioning cloning, that suggests you should clone - but then the subsequent paragraph suggests not :(
Here's a implementation using Java 8's new java.time package, so you can ditch java.util.Date and java.text.SimpleDateFormat:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
String text = "2013-05-23T09:18:07 p.m..380+0000";
Map<Long, String> map = new HashMap<>();
map.put(0L, "a.m.");
map.put(1L, "p.m.");
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'hh:mm:ss ")
.appendText(ChronoField.AMPM_OF_DAY, map)
.appendPattern(".SSSZ").toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(text, formatter);
System.out.println(dateTime);
}
}
Running it yields:
2013-05-23T21:18:07.380Z
Do it like this
String time="2013-05-23T09:18:07 p.m..380+0000";
int index1=time.indexOf("");
int index2 = time.indexOf(".."); // or you can give p.m. as argument if you want it to stop before pm
String result = time.substring(index1,index2);
System.out.print(result);
This has the following result
2013-05-23T09:18:07 p.m
I hope this helps
Just remove the p.m. part via string manipulation. It is redundant.
Than use a simple SimpleDateFormat to do the parsing.
Something along these lines:
String whatever = "2013-05-23T09:18:07 p.m..380+0000";
whatever = whatever.replaceAll(" p.m..", ":").replaceAll(" a.m..", ":");
System.out.println(whatever);
S
String pattern = "yyyy-MM-dd'T'hh:mm:ss:SSS'Z'";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
Date date;
try {
date = format.parse(whatever);
System.out.println(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Update
As pointed about by IAN, I missed out that the hours are not in 24hour format.
I did however get the millisecond part correct, and added the timezone part to Jon Skeet's answer to get:
String text = "2013-05-23T09:18:07 p.m..380+0000";
String pattern = "yyyy-MM-dd'T'hh:mm:ss aa'.'SSSZ";
SimpleDateFormat format = new SimpleDateFormat(pattern);
DateFormatSymbols symbols = format.getDateFormatSymbols();
symbols = (DateFormatSymbols) symbols.clone();
symbols.setAmPmStrings(new String[] { "a.m.", "p.m."});
format.setDateFormatSymbols(symbols);
Date date = format.parse(text);
System.out.println(date);