1

I have a @GetMapping mapped controller method with 3 Request Parameters: id, startDate, and endDate.

I want it to accept timestamps for both date parameters, but only get it working using ISO formatted strings.

My Method looks like below:

@GetMapping("/getNumberOfHolidays")
public ResponseEntity<Properties> getNumberOfHolidays(@RequestParam Integer locationId, 
        @RequestParam("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date startDate,
        @RequestParam("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date endDate){
    Integer noOfDays = 0;
    Properties prop = new Properties();
    try {
        noOfDays = service.getNumberOfHolidays(locationId, startDate, endDate);
        prop.setProperty("Number of Holidays", noOfDays.toString());
    } catch(Exception e) {
        //return
    }
     //return
}

When I invoke this method with startDate = 2020-08-01 and endDate = 2020-08-10 (both in YYYY-mm-DD), it's working as expected and properly converts the strings from the url.

Example:

   http://localhost:8080/TrackContract/getNumberOfHolidays?locationId=2&startDate=2020-08-01&endDate=2020-08-10

But when I call the method with timestamps like startDate = 1596220200000 and endDate = 1596997800000 it's not working(giving 400 Bad Request in postman)

Example:

   http://localhost:8080/TrackContract/getNumberOfHolidays?locationId=2&startDate=1596220200000&endDate=1596997800000

I tried to set the timestamp value to request param like below:

       @RequestParam("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
       @RequestParam("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate

But that didn't work. Can someone help me here how can I set timestamp value to the RequestParam startDate and endDate?

Clijsters
  • 4,031
  • 1
  • 27
  • 37
Tech_sharma
  • 117
  • 2
  • 11
  • 1
    Does this answer your question? [Convert Unix timestamp to Java Date, Spring RequestParam](https://stackoverflow.com/questions/29196466/convert-unix-timestamp-to-java-date-spring-requestparam) – Clijsters Jul 22 '20 at 15:37
  • do you want both versions in one endpoint: timestamps and iso formatted strings? – Planck Constant Jul 22 '20 at 15:41
  • `1596220200000` is `2020-07-31T18:30:00Z` and `1596997800000` is `2020-08-09T18:30:00Z`, which means that they are not the `2020-08-01` and `2020-08-10` values of your first example, unless you adjust them for time zone. – Andreas Jul 22 '20 at 15:41

2 Answers2

2

1596220200000 is not a date, it's a number.

In this case, it's a number that can be interpreted as the number of milliseconds since epoch, but it is just a number. To convert to a date, you have to do it.

public ResponseEntity<Properties> getNumberOfHolidays(@RequestParam Integer locationId, 
        @RequestParam("startDate") long startMilli,
        @RequestParam("endDate") long endMilli) {
    Instant startInstant = Instant.ofEpochMilli(startMilli);
    Instant endInstant = Instant.ofEpochMilli(endMilli);

In the question, there are two examples:

startDate = 2020-08-01 and endDate = 2020-08-10
startDate = 1596220200000 and endDate = 1596997800000

However, 1596220200000 is 2020-07-31T18:30:00Z
and 1596997800000 is 2020-08-09T18:30:00Z

Assuming it was meant to produce the same date values are the first example, the dates must be adjusted to the India time zone.

ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime startDateTime = startInstant.atZone(zone);
ZonedDateTime endDateTime = endInstant.atZone(zone);

That will produce values 2020-08-01T00:00+05:30[Asia/Kolkata] and 2020-08-10T00:00+05:30[Asia/Kolkata].

You can then call toLocalDate() to get 2020-08-01 and 2020-08-10.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • If I go with the Number format then It will get changed based on the Zone and as my server is located in USA, so it will convert the number and make it as USA date. I won't get the exact result I am looking for. how can I make it generic irrespective to the zone. – Tech_sharma Jul 22 '20 at 16:07
  • @Tech_sharma Since values like `startDate = 1596220200000` are milliseconds since epoch in UTC, if the client takes a **local** date and converts to UTC as part of the conversion to milliseconds, you have to know the original time zone so you can undo it. You won't have that problem with `startDate = 2020-08-01`, so stick with only supporting that, if you want a date-only value without having time zone issues. – Andreas Jul 22 '20 at 19:12
0

When you specify:

@RequestParam("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
@RequestParam("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate

You are telling to parser how incoming data should look like, that's why your first case is working. In you second case you only provide number (probably ms since epoch) and that is not correct ISO date format. If you want to obtain ms. from already set LocalDateTime (your first case) you can use following code:

LocalDateTime ldt = // this is already parsed from request param
ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles")); // specify your time zone
long millis = zdt.toInstant().toEpochMilli();

If you want to send timestamp's in ms or any number format directly to your API then just use @RequestParam("startDate") Long startdate. You can convert ms since epoch to LocalDateTime as well but there are lot of resources how to do it online.

Norbert Dopjera
  • 741
  • 5
  • 18
  • As I understand OP, he already has `long millis` and that's not the problem. The issue is, (s)he wants the method to accept msecs as input parameter. – Clijsters Jul 22 '20 at 15:36
  • I edited my answer. Thus when OP's want to use numeric timestamp's there is not reason to use `@DateTimeFormat` annotation. This annotation is usually used only when you are expecting timestamp in human readable format (or any format you would like to). To accept numeric timestamp just use `Long` as parameter and then one can convert numeric value to `LocalDateTime` for example. – Norbert Dopjera Jul 22 '20 at 15:42
  • That's correct. That's why I linked that other question. OPs question was asked multiple times before on SO and was also answered some times, so imho it's a duplicate. – Clijsters Jul 22 '20 at 15:45
  • Sorry i missed that, your link provides answer's for all cases OP could have thought by his question. – Norbert Dopjera Jul 22 '20 at 15:47
  • Thanks. This solved my issue. But I am worried if timezone change I wont get the exact result. Is there any way I can make it generic instead of checking each and every timezone and FYI I am using MS SQL server and it's in USA but the application is in used from different region. – Tech_sharma Jul 22 '20 at 16:39