Laureant
Laureant

Reputation: 1019

Javascript date object without time zone

I've recently implemented a webview based mobile app for a cloudbased system, and I've come across a frustrating problem.

We store the dates in the database in the following format:

2016-10-11T11:09:00

In the desktop applications it comes up correctly as 2016/10/11 11:09:00.

However, in the mobile app (we use phonegap, so it's HTML + JS based), when I get this date string from the database via a PHP call, and I convert it, using 'new Date("2016-10-11T11:09:00")', it shows up with a timezone conversion, so for instance if I'm in GMT + 2, it will be 2016/10/11 13:09:00.

How can I prevent this?

Whenever I show the dates on the views, I use a date.toString("yyyy/MM/dd HH:mm:ss") formatting.

Also, I'm open to any suggestions, in terms of storing and showing datetime across multiple platforms. I found this yyyy-mm-ddThh:mm:ss formatting to be quite good and videly used, until I bumped into this javascript problem.

(I'm not a javascript or HTML expert, as far as you can tell)

LE: I don't want to convert the date to UTC string, I want the actual Date object, to be consistent with the database value, cause i'm hooking it up to an HTML datetime picker via AngularJS.

Upvotes: 8

Views: 52431

Answers (4)

Menelaos Kotsollaris
Menelaos Kotsollaris

Reputation: 5506

You can use Moment.js and define your own custom date formatter:

var formatter= 'YYYY-MM-DD[T]HH:mm:ss';
var date = new Date('July 17, 2018 03:24:00');
var time = moment(date).format(formatter);
console.log('Time: ',time);

Fiddle: https://jsfiddle.net/mkotsollaris/3krdttm3/

Upvotes: 2

drlff
drlff

Reputation: 256

Ran into the same issue. Storing in yyyy-mm-ddThh:mm:ss format, but needed to convert it to date on client for a countdown timer calculation (needed to create 2nd date -> subtract difference -> create countdown timer). Logic was correct in browser, incorrect and inconsistent in Ionic2/cordova app webviews. Interesting: my wife and I both have the same phone make/model, and the dates would show up different on hers than mine (!).

Haven't extensively tested, but here is a little function that takes the string and returns a date... working consistently on my phones and browser:

const someDateStrFromServer: string = "2017-08-26T15:30:25";
const date: Date = DateUtils.overrideTimezone(someDateStringFromServer);

// these methods are in Class DateUtils {}
// input: string, output: Date
public static overrideTimezone(dateStr: string): Date {
    const date: Date = new Date(dateStr);
    const hours: number = date.getHours();
    const tIndex: number = dateStr.indexOf("T");
    const dateStrHours: number = +(dateStr.slice(tIndex + 1, tIndex + 3));
    const tzOffset =  DateUtils.getTimezoneOffset("h");

    // compares hours sliced from string and hours from date. if different,
    // then I know timezone was calculated into the Date

    if (dateStrHours === hours) return date;  // everything's OK

    // webview factored in timezone, so add it back to correct
    else return new Date(date.setHours(date.getHours() + tzOffset));

}

// can scale it to include "ms", "s", "m", etc
public static getTimezoneOffset(unit = "h") {
    switch(unit) {
        case "h": 
            return (new Date()).getTimezoneOffset() / 60;
        default:
            return (new Date()).getTimezoneOffset() / 60;
    }
}

Upvotes: 1

Samvel Petrosov
Samvel Petrosov

Reputation: 7706

You can use this little function for getting your result

function getCorrectString(dateTimeString){
     var a  = new Date(dateTimeString);
     return a.getFullYear()+'/'
     +('00'+(a.getMonth()+1)).substring(('00'+(a.getMonth()+1)).length-2) +'/'
     +('00'+a.getDate()).substring(('00'+a.getDate()).length-2)+' '
     +('00'+a.getHours()).substring(('00'+a.getHours()).length-2)+':'
     +('00'+a.getMinutes()).substring(('00'+a.getMinutes()).length-2)+':'
     +('00'+a.getSeconds()).substring(('00'+a.getSeconds()).length-2);
}

getCorrectString('2016-10-11T11:09:00')

//result :
//"2016/10/11 11:09:00"

Upvotes: 0

mikoni
mikoni

Reputation: 449

What is it that you actually want to achieve? If you want to show the timestamps always as they are ignoring timezone information, you might make things quite confusing to the user when those timestamps might show future time to some of the users. For example: someone modifies data and another user in US west coast views the data and sees the timestamp pointing to the future.

Maybe something you wan to use is Data.toUTCString(), that shows the timestamp so that you will have GMT as a timezone. Then it will be clear that to the users that this timestamp is not in their timezone. Also you might want to have timezone information appended to the timestamp string so that the conversions happen correctly. If you your timestamps are in UTC (or Zulu time) you can add "Z" to the end of the string. RFC 2822 Section 3.3 defines that date and time should express local time, but at least with node.js if you leave timezone information out, it seems to express UTC time. So adding the timezone information will make your life easier (would be even better if you would add timezone information in the in the string that you store in your database).

As an example:

var timestamp = "2016-10-11T11:09:00";
var d = new Date(timestamp);
// or
d = new Date(timestamp + "Z");

// Then showing the date
d.toString();
// or without the converting it to user's local timezone
d.toUTCString();

I hope this helps.

Upvotes: 4

Related Questions