37

I was trying to post some data to my REST api which has date. Now while I debug, my date parameter is a JS Date object with correct date in my timezone: Tue Apr 04 2017 00:00:00 GMT+0530

after it leaves my code, and I see the same in network tab, it is converted to UTC date: "2017-04-03T18:30:00.000Z"

I searched for the solution according to which I need to include locale file of angular in my index.html which I did:

<script type="text/javascript" src="resources/js/angular/angular-locale_en-in.js"></script>

but it doesn't help. I've seen solutions like adding date format to filter or something, but I want a global solution. Any help? Thanks :)

pranavjindal999
  • 2,937
  • 2
  • 26
  • 35
  • 1
    Not clear what specific problem is or what you are trying to change – charlietfl Apr 19 '17 at 13:22
  • 1
    I'm selecting 4th April on my UI and server is getting 3 April in UTC. my rest apis are third party and can not change them. I want to handle this issue globally – pranavjindal999 Apr 19 '17 at 13:26
  • 1
    but when you convert utc back to local will be the same .. 4th april. Still not clear what objective is – charlietfl Apr 19 '17 at 13:28
  • 2
    that is what I'm saying, I cannot ask api to convert utc date to local timezone. they want date in local timezone already. – pranavjindal999 Apr 19 '17 at 13:29
  • so transform date object to string yourself using whatever format api expects – charlietfl Apr 19 '17 at 13:31
  • this is already an issue at thousands of places in my application. I wanted a global solution.. – pranavjindal999 Apr 19 '17 at 13:32
  • can use a httpInterceptor to do it globally ... iterate data properties and convert if they are date objects – charlietfl Apr 19 '17 at 13:33
  • interceptor is to modify the http request, not the payload which varies with request. I think there must be a better way of doing that. I just want that my date should be sent with the same timezone, without any modification – pranavjindal999 Apr 19 '17 at 13:49
  • no... can modify the payload in interceptor ... or headers or any part of request – charlietfl Apr 19 '17 at 14:15
  • 2
    or modify Date.prototype.toJSON() which is what creates that string. But modifying native api is not a good practice – charlietfl Apr 19 '17 at 14:16
  • @pranavjindal999 check my answer i hope it will fulfill the requirements. – Debug Diva May 01 '17 at 16:25
  • I am having a similar issue, in my case, I am getting string date from API response, and while reading that response, the date automatically converts to -1 day. My system timezone is IST and if I change it to some other time zone like ITC-6, this gets resolves. So what is the exact issue here and how can I resolve it so that it works in any time zone? – Harshad Vekariya Oct 18 '21 at 13:24

10 Answers10

25

Handling date, time, and timezone have confused me too. May be this answer gives you some insight on how you can handle them.

Try the following code in Chrome's developer console and see how same date is presented in different formats:

var date = new Date();
date.toISOString(); // "2017-04-29T09:54:28.714Z"
date.toGMTString(); //"Sat, 29 Apr 2017 09:54:28 GMT"
date.toLocalString(); //"4/29/2017, 3:24:28 PM"

Any date that you create on client always records the date at zero timezone offset i.e. UTC+/-00:00 Z. For simplicity you may think UTC and GMT as same. When it comes to display purpose the same date is presented as per the browser's timezone. If you do console.log (date) it'll output Sat Apr 29 2017 15:24:28 GMT+0530 (IST) but that doesn't mean that the internal recording of the date is as per browser's timezone. It's just presented on screen/console as per browser's timezone.

Look at date representations not as being converted from one timezone to another but look at them as different representation of the same date. In your browser it is represented as GMT+0530 offset and when it is sent to server it is the same date at zero timezone offset.

As per your comment, if you choose 4th Apr at 00:00 AM in GMT+0530 timezone, internally it'll be 3rd Apr at 18:30 PM in at GMT+0 i.e. zero timezone offset. Let it go to server as it is. When you need to use this date, it comes back from server as 3rd Apr and it'll be displayed in browser as per the browser's timezone offset. There is no conversion involved, it is one date with different representation.

I once asked a related question, may be this adds more clarification.

And overall, this answer is still same as @geminiousgoel and @charlietfl answers.

Community
  • 1
  • 1
Ritesh Jagga
  • 1,387
  • 1
  • 11
  • 23
  • 2
    Sending the date as `2017-04-03T18:30:00.000Z` instead of `2017-04-04T00:00:00.000+05:30` might not be desirable at all, because the client's original time zone info is lost. For example, suppose the backend needs to validate that the time is entered is 'before noon' in the client's time zone. The check will fail for the former date and succeed for the latter, even though they represent the same moment. – sgdesmet Oct 19 '18 at 11:15
  • 1
    I don't know how this got so many upvotes, it does not solve the problem, just adds another by "letting the date go as it is", so letting it go to the Back-End as the incorrect one. – Renis1235 May 27 '21 at 19:40
  • @Renis1235 When you say "letting the date go as it is" is a problem, do you expect or have a scenario to send the timezone offset along with the date? – Ritesh Jagga May 31 '21 at 11:58
  • @RiteshJagga I have a use-case where the user must select a date for an Invoice, and basically, I do not care about the timezone, I just need the specific, correct date. When the user selects 1.1.2021, 31.12.2020 will be sent to my server-side, which makes things even more complicated. – Renis1235 May 31 '21 at 12:58
  • If you don't care about the timezone, I think having dates in 2020-12-31 HH:MM:SS Z format is fine but I would suggest to record your dates in complete date & time format. When it comes to display, date time will be displayed per the system's timezone. AFAIK, You need timezone offset and conversions for scenarios like e.g. "I want all my reports date and time to display in this particular timezone only, which is different than the system's timezone. – Ritesh Jagga May 31 '21 at 15:45
  • This was a wonderful explanation, thank you! – Phil Nov 02 '22 at 23:04
5

Scenario :

Send date from UI into API call as an epoch time (UNIX Time) instead of date string. You can use getTime() method to convert the date into epoch time.

var dateStr = "Tue Apr 04 2017 00:00:00 GMT+0530";

var dateEpoch = new Date(dateStr).getTime();

console.log(dateEpoch); // 1491244200000 (Local Time)

At receiver end, they have to convert this epoch time (UNIX time) into Date again.It will give the same local date\time that pass from the UI.

Sample screenshot enter image description here

Debug Diva
  • 26,058
  • 13
  • 70
  • 123
4

Like charlietfl suggested, probably the global hack would be to override Date.prototype.toJSON() method, but that's not a good practice.

Where are you using your $http.post call? The best place to submit an $http request would be in a service. If you use a service, then I suggest you to enwrap your public service API, so that you could have "public" and "private" methods: these could be utilities to perform common operations, such as data transformations, validations..

angular.service('bookStoreService', ['$http'], function($http) {
    var normalizeBooks = function(booksArray){
        booksArray.forEach(function(book){  
            // do something on the book
        });
    };

    var updateBooks = function(books){
       normalizeBooks(books);
       $http.post('myurl', books);
    };

    return {
       updateBooks : updateBooks
    };
});
Redd Sanso
  • 51
  • 4
3

Passing UTC date to server is desired behavior. The client APIs are supposed to handle UTC time instead of assuming the dates are all local dates.

But anyways, you can convert the date to string based on local time zone, and pass the string to server.

Dada
  • 49
  • 3
  • Good idea @Dada – Anas May 17 '17 at 19:38
  • 2
    This may not be desired behaviour at all, as you are effectively losing information: the timezone the date and time were entered in, which might be important information. – sgdesmet Oct 19 '18 at 11:00
3

i think you just can pass it as string (if the api you use accept strings) with the format you need, let say "Tue Apr 04 2017 00:00:00 GMT+0530" and save it in back-end as string and then when you retrieve it, it will be string and so it will not be changed in any way.

Ahmad Abu Saa
  • 718
  • 6
  • 12
2

Jindal saab, It will work like this. When we select any date with date picker or just pass any value it takes the original local date but when we pass that value further it converts it into UTC, thereafter it needs to convert to local zone again at receiving end. Database saves date-time in UTC format.

geminiousgoel
  • 319
  • 1
  • 4
  • 15
2

Did you added the angular-locale_en-in.js library to your app? Something like this....

angular.module('myAngularApp', [
    'ngLocale'])

Otherwise, the js library won't have any effect in your angular application.

Gi1ber7
  • 632
  • 1
  • 11
  • 22
1

Append UTC at the end so that Browser converts it into UTC date

var dateToServer =new Date(dateFromUser+" UTC"); now the dateToServer will be UTC DateTime format.

Sharan Rai
  • 94
  • 8
  • In some cases it could help appending "T00:00:00Z" after date. Check formats https://www.utctime.net/ – apincik May 12 '20 at 21:03
0

Json serializer parse date from string. On a client the date properties are stored as local date in browser time zone. When you are posting your object to server all date properties converts to utc string. In most cases it is a properly behavor. But sometimes you need set and send date in a server time zone. Often it is need when you should set only date whitout time. In that case you should define string propertie and set it manualy. I usaly apply this trick.

class Obj{
 d: Date
}

class ObjDto{
 constructor(obj: Obj){
   this.d= dateTimeToIsoLocalDateString(obj.d)
 }
 d: string
}

...

export function DateTimeToDate(date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
}

export function dateTimeToIsoLocalDateString(dateTime: Date): string {
    if (dateTime === null) {
        return null;
    }
    let date = DateTimeToDate(dateTime);
    let res = date.toISOString().replace("Z", "");
    return res;
}

For more understanding this theme you may learn this topic

trueboroda
  • 2,650
  • 26
  • 24
0
//in res data of rest service in x the value is date in y value of y-axis     
     for (const i in res) {
        console.log(i);
        const a = {x: new Date(this.mimikatzlog[i].x), y: this.mimikatzlog[i].y};
        this.policies.push(a);
Asad Javed
  • 51
  • 4
  • 4
    Code-only answers are considered low quality: make sure to provide an explanation what your code does and how it solves the problem. It will help the asker and future readers both if you can add more information in your post. See also Explaining entirely code-based answers: https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers – borchvm Dec 04 '19 at 07:04