Criteria Builder for date range check - java

I am trying to check if 'toDate' lies within the range , for that i tried 2 approaches but both haven't worked for me
approach 1:
if (MyEntity.getFromDate() != null
&& MyEntity.getToDate() != null)) {
predicate.getExpressions()
.add(criteriaBuilder.between((root.<Date>get("toDate")), MyEntity.getFromDate(),MyEntity.getToDate()));
approach 2
if(MyEntity.getFromDate() != null
&& MyEntity.getToDate() != null) {
DateFormat dateFormat = new SimpleDateFormat(Constants.DBDATEFORMAT);
String fromDateInString = dateFormat.format(MyEntity.getFromDate());
String toDateInString = dateFormat.format(MyEntity.getToDate());
String[] fromDateSplitation = fromDateInString.split(" ");
String[] toDateSplitation = toDateInString.split(" ");
StringBuilder startLimit = new StringBuilder();
StringBuilder endLimit = new StringBuilder();
startLimit.append(fromDateSplitation[0]).append(" ").append("00:00:00");
endLimit.append(toDateSplitation[0]).append(" ").append("23:59:59");
Date fromDate;
try {
fromDate = dateFormat.parse(startLimit.toString());
Date toDate = dateFormat.parse(endLimit.toString());
MyEntity.setFromDate(fromDate);
MyEntity.setToDate(toDate);
predicate.getExpressions().add(criteriaBuilder.between(root.get("toDate"),
MyEntity.getFromDate(), MyEntity.getToDate()));
} catch (ParseException e) {
e.printStackTrace();
}
Can anyone tell me how to properly use Between and Equal for date with criteria builder ?

I've always used your first approach, but not specifying the generic on the Path. Could you maybe try:
.add(criteriaBuilder.between(root.get("toDate"),
MyEntity.getFromDate(),MyEntity.getToDate()));
and most importantly, are you certain that the toDate field of your Entity is Annotated with #Temporal(TemporalType.TIMESTAMP)

Related

unable to redirect response in rest controller

I made two RestController apis. On response of second api I wanted first api's response (which is a json response), so I tried to use HttpServletResponse.redirect. I also set required content type to it. But on second api response I got Unsupported Media Type Content type 'null' not supported.
first API
#GetMapping(value="checkStatus/{msisdn}",consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CoreResponseHandler> fetchOcsByDate2(#PathVariable(value="msisdn",required=true)String msisdn){
long l_time_start = System.currentTimeMillis();
List<Object[]> list = repository.getSingleCallDetail(msisdn);
if(list==null || list.size()==0) {
System.out.println("NO RECORD FOUND");
}
JSONObject objMain = new JSONObject();
for(Object[] objArr: list) {
JSONObject obj = new JSONObject();
String msisdn_ = objArr[0]==null?null:objArr[0].toString();
String songId = objArr[1]==null?null:objArr[1].toString();
String songName = objArr[2]==null?null:objArr[2].toString();
String status = objArr[3]==null?null:objArr[3].toString();
String lang = objArr[4]==null?null:objArr[4].toString();
String startDate = objArr[5]==null?null:objArr[5].toString();
objMain.put("status", status);
objMain.put("language", lang);
obj.put("id", songId);
obj.put("msisdn", msisdn);
obj.put("songName", songName);
objMain.put("subscription", obj);
}
long l_time_end = System.currentTimeMillis();
long l_diff = l_time_end-l_time_start;
if(list!=null && list.size()>0) {
return new ResponseEntity<CoreResponseHandler>(new SuccessResponseBeanRefined(HttpStatus.OK, ResponseStatusEnum.SUCCESSFUL, ApplicationResponse.SUCCESSFUL, objMain,l_diff+" ms"),HttpStatus.OK);
}
if(list==null || list.size()==0) {
return new ResponseEntity<CoreResponseHandler>(new SuccessResponseBeanRefined(HttpStatus.NOT_FOUND, ResponseStatusEnum.FAILED, ApplicationResponse.Failed, "not found",l_diff+" ms"),HttpStatus.NOT_FOUND);
}
return new ResponseEntity<CoreResponseHandler>(new SuccessResponseBeanRefined(HttpStatus.BAD_REQUEST, ResponseStatusEnum.FAILED, ApplicationResponse.Failed," > Bad request",l_diff+" ms"),HttpStatus.BAD_REQUEST);
}
no problem in output. ran smooth
second API
#GetMapping(value="verifyOtp/{msisdn}/{otp}",consumes=MediaType.APPLICATION_JSON_VALUE)
public void verifyOtp(#PathVariable(value="msisdn",required=true)String msisdn,
#PathVariable(value="otp",required=true)String otp,HttpServletResponse response) throws Exception{
long l_time_start = System.currentTimeMillis();
long l_time_end = System.currentTimeMillis();
long l_diff = l_time_end-l_time_start;
List<Object[]> list = repository.verifyOtp(msisdn,otp);
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
if(list!=null && list.size()>0) {
for(Object[] obj:list) {
String strDate = obj[3]==null?null:obj[3].toString();
Date dtDb = sdf.parse(strDate);
Date dtNow = new Date();
String strDtNow = sdf.format(dtNow);
dtNow = sdf.parse(strDtNow);
long ldtDb = dtDb.getTime();
long ldtNow = dtNow.getTime();
if(ldtDb>ldtNow) {
System.out.println("success within time");
int ii = repository.updateIsActive(msisdn);
response.setContentType("application/json");
response.sendRedirect("http://localhost:9393/crbt/api/subscriber/ivr/checkStatus/"+msisdn);
}
else {
System.out.println("failure time over!");
}
}
}
else {
}
}
second Api Response in postman
What I expected was first API's response. But its giving me some 415 content type error
How can I get first API's success json response from second api's response.. I even tried org.springframework.http.HttpHeaders but couldn't get desired output. What changes I had to do in order to get first Api's response in my second api response.
I have a strange feeling answering your questions, because I dislike the solution I'll provided. But it might help, so I'll give a try.
Basically, your Controller are just Spring beans, which means you can do is having a dependency, and second controller will call first controller. This will also change your method verifyOtp to make it change the return type.
Something like that:
...
#Autowired
private FirstController firstController;
...
#GetMapping(value="verifyOtp/{msisdn}/{otp}",consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CoreResponseHandler> verifyOtp(#PathVariable(value="msisdn",required=true)String msisdn,
#PathVariable(value="otp",required=true)String otp,HttpServletResponse response) throws Exception{
long l_time_start = System.currentTimeMillis();
long l_time_end = System.currentTimeMillis();
long l_diff = l_time_end-l_time_start;
List<Object[]> list = repository.verifyOtp(msisdn,otp);
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
if(list!=null && list.size()>0) {
for(Object[] obj:list) {
String strDate = obj[3]==null?null:obj[3].toString();
Date dtDb = sdf.parse(strDate);
Date dtNow = new Date();
String strDtNow = sdf.format(dtNow);
dtNow = sdf.parse(strDtNow);
long ldtDb = dtDb.getTime();
long ldtNow = dtNow.getTime();
if(ldtDb>ldtNow) {
System.out.println("success within time");
int ii = repository.updateIsActive(msisdn);
return firstController.fetchOcsByDate2(msidn);
}
else {
System.out.println("failure time over!");
return null;
}
}
}
else {
return null;
}
}
I think you are trying to achieve something uncommon, and to avoid having this dependency between controller, consider:
Change your use case. Make the second controller returning a HttpStatus.OK, and make the client do the next call to the first controller
Create a service in charge of loading the msidn, which will avoid duplicate code, and keep you in a more standard position to make our evolutions.
The issue occurred due to GetMapping .
#GetMapping(value="checkStatus/{msisdn}",consumes=MediaType.APPLICATION_JSON_VALUE)
replace with below in first Api:
#GetMapping(value="checkStatus/{msisdn}")

Avoiding a NullPointerException when the user enters invalid data

How can I avoid a NullPointerException here if the user passes a null value for a date? Ideally, I would use a simple if statement.
SimpleDateFormat dateFormatter = new SimpleDateFormat("MM/dd/yyyy");
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm");
String layupDate = dateFormatter.format(orderLayupDateSet.getLayupDate());
String layupTime = timeFormatter.format(orderLayupDateSet.getLayupDate());
if(layupDate == null) {
}
You validate the date (orderLayupDateSet.getLayupDate()) in a liner (just creating a new date if null here but you can do as you please);
(orderLayupDateSet.getLayupDate() == null) ? new Date() : orderLayupDateSet.getLayupDate()
You can also go the traditional
if (orderLayupDateSet.getLayupDate() == null) {
orderLayupDateSet.setLayupDate(new Date());
}
Or you can do it the other way around with a utility, and calling the utility function to check for you - seeing that you return a String in your example above. Like the below;
public class DateUtils {
public static String formatDateTime(Date dateOrNull) {
return (dateOrNull == null ? null : DateFormat.getDateTimeInstance().format(dateOrNull));
}
}
Which in your code can be
String layupDate = (orderLayupDateSet == null || orderLayupDateSet.getLayupDate() ? null : dateFormatter.format(orderLayupDateSet.getLayupDate()));

Avoiding a particular check for YYYY-MM--dd format in date

I have below method in which different date patterns have been handled
below is the method in which different date formats have been handled now
now for the particulat format YYYY-MM-dd i don't want it to go for the check where we are prefixing 20 before in code please advise how can i skip that part lets say if the date pattern is YYYY-MM-dd then avoid the logic of prefixing 20 in front of year
below is my code
public java.util.Date extractDate(String dateStr, String dateType) {
String[] datePatternsOfUk = { "d-M-yy", "d-M-yyyy", "d/M/yy", "d/M/yyyy", "yyyy-MM-dd","dd-MM-yy", "dd-MMM-yy","dd-MMM-yyyy","dd-MM-yyyy",
"dd/MM/yy","dd/MMM/yy","dd/MMM/yyyy"};
String[] datePatternsOfUs = { "M-d-yy","MM-dd-yy","M/d/yy","MM/dd/yy", "MM/dd/yy", "MMM-dd-yy",
"MMM/dd/yy", "MMM-dd-yyyy", "MM-dd-yyyy", "MMM/dd/yyyy",
"MM/dd/yyyy" };
java.util.Date date = null;
String[] datePatterns = datePatternsOfUk;
if (dateType.equals("US")) {
datePatterns = datePatternsOfUs;
} else if (dateType.equals("UK")) {
datePatterns = datePatternsOfUk;
}
///******code should not go in this check where date pattern is YYYY-MM-dd
int p = dateStr.lastIndexOf("/");
if (p == -1) {
p = dateStr.lastIndexOf("-");
}
String firstSubstring = dateStr.substring(0, p + 1);
String secondSubstring = dateStr.substring(p + 1);
if (p != -1 && secondSubstring.length() <= 2) {
secondSubstring = Integer.toString(2000 + Integer.parseInt(secondSubstring));
dateStr = firstSubstring + secondSubstring;
}
///****************************************//
try {
date = DateUtils.parseDate(dateStr, datePatterns);
} catch (ParseException ex) {
logger.error("##$$$$$### Error in invoice inside extractDate method : ##$$$$$$#### "
+ ErrorUtility.getStackTraceForException(ex));
}
return date;
}
You could avoid trying any inappropriate pattern by checking if the string "looks like" the pattern before parsing with the pattern.
The general way to do this is:
String datePattern = "yyyy-MM-dd"; // for example
String input;
if (input.matches(datePattern.replaceAll("\\w", "\\d"))) {
// the input looks like the pattern
// in this example "dddd-dd-dd" where "d" is any digit
// so go ahead and try the parse
}
You can enhance this logic to add:
if (input.matches("\\d\\d\\D.*")) {
// then it only has a two digit year, so add "20" to the front
}
if (!dateStr.equals("YYYY-MM-dd")) {
// code
}

adding Gregorian Calendar dates to an array and retrieving the date to print in a string

I am writing a credit card program. I want the program to use the current date every time the method is used to make a purchase and put the date into the array
private GregorianCalendar transDate;
public CreditCard(double amount,String storeName, GregorianCalendar transDate) {
this.amount=amount;
this.storeName=storeName;
transDate=new GregorianCalendar();
}
public void purchase(double amount, String storeName, GregorianCalendar date)throws Exception
{
if (numPurchases<purchases.length)
if (amount >0 )
if(amount+balance<=creditLimit)
if( GregorianCalendar.getInstance().getTimeInMillis()<=expDate.getTimeInMillis())
{
balance+=amount;
transDate=getTransDate();
purchases[numPurchases] = new CreditCard(amount, storeName,transDate);
numPurchases++;
}
else
{
throw new Exception("card expired");
}
else{
throw new Exception("insufficient credit");
}
else{
throw new Exception("invalid amount");
}
else{
throw new Exception("exceeded number of allowed purchases");
}
}
I would like to display the information in String info
info+="Purchases:\n";
for(int index=0;index<numPurchases;index++){
info+="["+(index+1)+"] ";
info+=transDate.get(Calendar.YEAR)+"\t";
info+= purchases[index].getStoreName()+"\t";
info+=(formatter.format(purchases[index].getPurchase()))+"\n" ;
}
how do I need to set up the code to use the current date and add it to the array and display it in the string
Why don't you use a List implementation instead of an array? You can override the toString method to print it the way you want.
final SimpleDateFormat formatter = new SimpleDateFormat("dd MM yyyy");
List<Calendar> dates = new ArrayList<Calendar>() {
private static final long serialVersionUID = -5079502477457556887L;
#Override
public String toString() {
Iterator<Calendar> i = iterator();
if (!i.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
Calendar c = i.next();
sb.append(formatter.format(c.getTime()));
if (! i.hasNext())
return sb.append(']').toString();
sb.append(", ");
}
}
};
dates.add(Calendar.getInstance());
dates.add(Calendar.getInstance());
System.out.println(dates);
What does your getTransDate() function do? Ideally it should return the transDate variable of CreditCard object. To calculate transDate for a purchase, you are better off renaming the method to calculateTransDate() or something like that.
Once you have getTransDate() method returning the transDate, your info string can be :
info+="Purchases:\n";
for(int index=0;index<numPurchases;index++){
info+="["+(index+1)+"] ";
info+=purchases[index].getTransDate().get(Calendar.YEAR)+"\t";
info+= purchases[index].getStoreName()+"\t";
info+=(formatter.format(purchases[index].getPurchase()))+"\n"
}

Check date format before parsing

I am parsing several documments with the field Duration. But in the differents files, it is in differnt formats, ex:
"Duration": "00:43"
"Duration": "113.046"
"Duration": "21.55 s"
I want to parse all of them to the format "Duration": "113.046", how could I check before any parsing in wich format it is??
Some conditions before this piece of code, because this is not right for all of them:
Long duration;
DateFormat sdf = new SimpleDateFormat("hh:mm:ss");
try {
Date durationD = sdf.parse(totalDuration);
Date zeroSec = sdf.parse("00:00:00");
duration = durationD.getTime() - zeroSec.getTime();
} catch (Exception e) {
duration = Long.parseLong(totalDuration);
}
Thanks in advance
You could match the pattern with help of regex and then format accordingly. Here's a kickoff example:
Map<Pattern, DateFormat> dateFormatPatterns = new HashMap<Pattern, DateFormat>();
dateFormatPatterns.put(Pattern.compile("\\d{1,2}:\\d{2}"), new SimpleDateFormat("H:m"));
dateFormatPatterns.put(Pattern.compile("\\d{1,3}\\.\\d{3}"), new SimpleDateFormat("s.S"));
dateFormatPatterns.put(Pattern.compile("\\d{1,2}\\.\\d{2} s"), new SimpleDateFormat("s.S 's'"));
String[] strings = { "00:43", "113.046", "21.55 s" };
DateFormat finalFormat = new SimpleDateFormat("HH:mm:ss");
for (String string : strings) {
for (Pattern pattern : dateFormatPatterns.keySet()) {
if (pattern.matcher(string).matches()) {
Date date = dateFormatPatterns.get(pattern).parse(string);
String formattedTime = finalFormat.format(date);
System.out.println(formattedTime);
break;
}
}
}
This yields here
00:43:00
00:01:53
00:00:21
If these are all your known input formats, then convert your input to your expected date format.
Just string-replace all : with . and remove s.
Do not forget to strip the spaces, too. By the way, "113.046" seems a bit odd date format to me - if I were in your shoes, I would have used some of the standard date time formats and convert the irregular ones.
My solution, not smart at all:
long DurationFixer(String duration){
long durationLong = 0;
if(duration.contains(":")){
DateFormat sdf = new SimpleDateFormat("mm:ss");
try {
Date durationD = sdf.parse(duration);
Date zeroSec = sdf.parse("00:00:00");
durationLong = durationD.getTime() - zeroSec.getTime();
} catch (Exception e) {
durationLong = (Long.parseLong(duration))/1000;
}
}
else{
String r = "";
if(duration.contains("s")){
for (int i = 0; i < duration.length()-2; i ++) {
if ((duration.charAt(i) == '.'))
break;
else
r += duration.charAt(i);
}
}
durationLong = Long.valueOf(r);
}
return durationLong;
}
If someone could find a better solution, please, tell me.
Thanks everybody!

Categories