1

Im struggling understanding whats happening when I select a date from my angular calendar for example "29/05/2021" and send it to my backend it arrives as "Fri May 28 19:00:00 COT 2021" one day less.

In my calendar im setting the date timezone with pipes as utc-5 which is my timezone like this:

{{todo.targetDate | date: 'yyyy-MM-dd':'utc-5' | uppercase}}

when I do console.log(todo.targetDate) before sending the JSON which contains the date I can see it prints "2021-05-29" which is correct.

But when it arrives at my backend (Java) when I print I get "Fri May 28 19:00:00 COT 2021", I think the problem is im only changing the date format visually in angular, but not its value, but since the console prints the correct format in angular, im confused now.. can you plesae tell me any hint to find out the problem? Im learning front end skills so please be soft.

EDIT: Maybe the problem is more in my backend, here is an image of how the date looks inside the JSON object which is very strange: date with strange format

And here is my code in the backend java:

@PutMapping(path = "/jpa/users/{username}/todos/{id}")
public ResponseEntity<Todo> updateTodo(@PathVariable String username, @PathVariable long id, @RequestBody Todo todo)
        throws ParseException {

    System.out.println(todo.getTargetDate());
    // Fri May 28 19:00:00 COT 2021
    LocalDate fechaBien = todo.getTargetDate().toInstant().atZone(ZoneId.of("UTC-05:00")).toLocalDate();
    System.out.println(fechaBien);
    // 2021-05-28
    // I added 1 day to make it 2021-05-29 but this is bad because then at angular it appears as 2021-05-30 XD
    fechaBien = fechaBien.plusDays(1);
    // Then I parse the localdate to Date because thats the type of this property
    todo.setTargetDate(Date.from(fechaBien.atStartOfDay(ZoneId.of("America/Bogota")).toInstant()));
    System.out.println(todo.getTargetDate());
    // Sat May 29 00:00:00 COT 2021
    


    return new ResponseEntity<Todo>(todo, HttpStatus.OK);

}
BugsOverflow
  • 386
  • 3
  • 19
  • You should check the network panel of your browser to see the request that is actually sent from your frontend to your backend. This way you'll be sure which one is "not correct" – Gaël J May 20 '21 at 19:51
  • 1
    The timezone of your Java application is UTC-5. On the line is UTC-0. You parse date received from the server from UTC-5 to UTC-0 (the date pipeline do that trick in the layout template). Check the interface specification what's expected in the API and send the date in that format. It seems that the server expect that you have to send the date in UTC-5 format. Be aware that the date you generate on UI side are in UTC-0 format. – Jasper Huzen May 20 '21 at 20:01
  • @ Gaël J yes thanks for the advice, I though I would find the mistake there but actually is also sending targetDate: "2021-05-29" in the json too, why it changes to one day less when it arrives? – BugsOverflow May 20 '21 at 20:04
  • I added java code and show how the date comes back in the json, in a strange format for me first time i see that, hope you can help me with that info – BugsOverflow May 20 '21 at 21:10

2 Answers2

3

There is nothing wrong with the date-time that your backend server is receiving from Angular. Angular is sending the date-time in UTC and your backend server is receiving the same date-time but your backend server has a timezone offset of UTC - 5 hours. The same instant is interpreted differently in different time zones e.g. 2021-05-29T00:00:00 in UTC is 2021-05-28T19:00-05:00 in your backend server's timezone.

The java.util.Date object (in your case, it is todo.getTargetDate()) is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value.

Note that the legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat etc.) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

A demo using java.time, the modern date-time API:

import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Fri May 28 19:00:00 COT 2021";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E [MMMM][MMM] d H:m:s zzz u", Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);

        // The corresponding date-time in UTC
        Instant instant = zdt.toInstant();
        System.out.println(instant);
    }
}

Output:

2021-05-28T19:00-05:00[America/Bogota]
2021-05-29T00:00:00Z

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Your next steps:

Convert the java.util.Date object into Instant as follows:

Instant instant = todo.getTargetDate().toInstant();

Then, you can obtain the ZonedDateTime from it as follows:

ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Bogota"));

Learn more about java.time, the modern date-time API* from Trail: Date Time.


* 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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • I will try what you are telling me, but im still wondering if my angular is sending the date wrong? Because if I select in the calendar 29/05/2021 why it arrives as 28/05/2021? I will carefully check what you just answer – BugsOverflow May 20 '21 at 21:18
  • 2
    @BugsOverflow - Your angular is sending the date in UTC and your blackened server is receiving it the same date but your blackened server has a timezone offset of UTC - 5 hours. The same instant is interpreted differenty in different time zones. `2021-05-29T00:00:00` in UTC is `2021-05-28T19:00-05:00` in your backend server's timezone. This is what I have demonstrated. – Arvind Kumar Avinash May 20 '21 at 21:20
  • Hey I now think understand it much better, your answer I havent analyzed alot yet cause im kind on a hurry, but now I get it the date is fine, but java has utc-5 so that why it takes it like that (minus some hours), because now I told both of them to be with "utc" only, not utc-5 and now it is saving it correctly, now I need to figure out how to tell both to be in utc-5 the proper way – BugsOverflow May 20 '21 at 21:42
  • @BugsOverflow - I recommend you keep it in UTC. However, as I mentioned earlier there is nothing wrong with the date that is being produced and the one that is being consumed. It's just different interpretations because of different time zones. I recommend you go through my answer two-three times to grasp it fully and also switch to the modern date-time API. It just takes one step to switch and then the modern date-time API will save you hundreds of hours by virtue of its cleanliness. Feel free to comment in case of any further doubt/issue. – Arvind Kumar Avinash May 20 '21 at 21:50
  • Check your spell-checker. Only [Cajuns](https://en.wikipedia.org/wiki/Cajuns) run [blackened](https://en.wikipedia.org/wiki/Blackening_(cooking)) servers. ;-) – Basil Bourque May 20 '21 at 23:52
1

We cannot solve your problem because you provide none of your code parsing the date string. You are not even clear about what string exactly are you sending. I can only give general guidelines.

If you only care about the date, without the time-of-day and without the time zone, parse as java.time.LocalDate.

LocalDate.parse( "2021-05-29" ) 

Never use the legacy classes Date or Calendar.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154