2

I want to convert my local time (shown below) to UTC. Local time can belong to any timezone which a user belongs to. I just want to convert it to UTC format.

Local Time : '2015-12-04 19:05:48'

How do I achieve this requirement in JavaScript or AngularJS?


Update

My Original date/time string as like this "Mon March 28 2016 23:59:59 GMT -0600 (CENTRAL DAYLIGHT TIME)" and I have converted them to "2016-03-28 23:59:59 CDT" as requested date format. But again, I need to convert this interim output in to UTC in the same interim output format "YYYY-MM-DD HH:MM:SS". How do I achieve this

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
JsLearner
  • 109
  • 1
  • 5
  • 16
  • `new Date( '2015-12-04 19:05:48').toUTCString()` – Lewis Apr 04 '16 at 15:17
  • *"any timezone which user belongs to"* – what does that mean exactly? Do you know the timezone/or can programmatically figure out the timezone? Otherwise that date string is rather meaningless and *cannot* be converted to UTC. – deceze Apr 04 '16 at 15:25
  • My Original date/time string as like this “Mon March 28 2016 23:59:59 GMT -0600 (CENTRAL DAYLIGHT TIME)” and i have converted them to 2016-03-28 23:59:59 as requested date format. But again i need to convert this interim output in to UTC in the same output format YYYY-MM-DD HH:MM:SS. How do i acheive this? – JsLearner Apr 04 '16 at 16:04
  • Why did you remove the offset? "CDT" could be anything since there is no standard for naming or abbreviating time zones. `GMT -0600` (or just `-0600`) is exact and unambiguous. Also, if you are going to "convert" it to UTC, you **must** keep the timezone (either "Z" or "+0000"). – RobG Apr 05 '16 at 01:29
  • Does this answer your question? [Convert date and time to UTC](https://stackoverflow.com/questions/37117374/convert-date-and-time-to-utc) – Michael Freidgeim Jan 09 '22 at 04:01

3 Answers3

1

You can try this.
fiddle: https://jsfiddle.net/shuNaka/v891skuh/

const datetime = "2020-02-12 10:30:00";
const timezone = "Asia/Tokyo";

document.getElementById("localtime").innerHTML = datetime;
document.getElementById("timezone").innerHTML = timezone;
document.getElementById("utctime").innerHTML = getUtcFromLocaltime(datetime, timezone);

function getUtcFromLocaltime (localtimeString, timezone) {
    // Change it to moment object
    const localTime = moment(localtimeString, 'YYYY-MM-DD HH:mm:ss', true);
    // Get the timezone
    const timeDiff  = moment().tz(timezone).format('ZZ')
    // Get the time difference
    let numTimeDiff = Number(timeDiff.substr(1)) / 100;
    numTimeDiff = hourAdjust(numTimeDiff);
    // Get UTC from the timezone(+0900)
    if (timeDiff.charAt(0) === '+') {
        return localTime.subtract({hours: numTimeDiff}).format('YYYY-MM-DD HH:mm:ss');
    } else if (timeDiff.charAt(0) === '-') {
        return localTime.add({hours: numTimeDiff}).format('YYYY-MM-DD HH:mm:ss');
    }
}


function hourAdjust (hour) {
    let mhour = Math.floor(hour);
    let min = (Math.floor(hour * 100) % 100) / 6;
    return Number(mhour+"."+min);
}
lechat
  • 390
  • 2
  • 15
0

You can create a new local date based on the UTC values of the original (local) date.

var localDate = parseDate('2015-12-04 19:05:48 CDT'); // With or without CDT (still works)

document.body.innerHTML  = [
  '- Local Time: ' + formatDate(localDate),
  '-   UTC Time: ' + formatDate(localDateToUTC(localDate))
].join('\n');

function parseDate(dateString) {
  var tokens = dateString.split(/[-: ]/g).slice(0, 6).map(function(token) { return parseInt(token, 10); });
  tokens[1] -= 1; // Subtract 1 from month.
  return newInstance(Date, tokens);
}

function formatDate(date) {
  function pad(val, pattern) { return (pattern + val).substr(-pattern.length); } 
  return date.getFullYear() + '-' + pad(date.getMonth() + 1, '00') + '-' + pad(date.getDate(), '00') + ' ' +
    pad(date.getHours(), '00') + ':' + pad(date.getMinutes(), '00') + ':' + pad(date.getSeconds(), '00');
}

function localDateToUTC(localDate) {
  return new Date(localDate.getUTCFullYear(), localDate.getUTCMonth(), localDate.getUTCDate(),
                  localDate.getUTCHours(), localDate.getUTCMinutes(), localDate.getUTCSeconds());
}

function newInstance(clazz, arguments, scope) {
  return new (Function.prototype.bind.apply(clazz, [scope].concat(arguments)));
}
body {
  font-family: monospace;
  white-space: pre;
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • I am getting the below assignment locaDate as Invalid Date in Firefox browsers. var localDate = new Date('2015-12-04 19:05:48'); – JsLearner Apr 04 '16 at 15:57
  • 1
    Your code is giving the result as NaN Nan in firefox and not working as expected. – JsLearner Apr 04 '16 at 16:13
  • @JsLearner I added a parse date method. It will extract all of the date and time values as integers and pass them to the Date constructor to create a new date. It just so happens that they are already ordered year, month, day, hour, minute, second. This makes injecting the tokens easy :) – Mr. Polywhirl Apr 04 '16 at 16:28
  • 1
    your answer is one of the best answer for date time issue on stackoverflow. Great stuff. Thanks a ton. I have an other datetime question which is unresolved for a while, could you please help me out? https://stackoverflow.com/questions/35807298/javascript-how-do-i-convert-utc-date-time-to-est-hours-using-pure-javascript – JsLearner Apr 04 '16 at 17:14
  • @JsLearner: Thanks, I went ahead and abstracted the new Date instance code into a method that works for all classes. – Mr. Polywhirl Apr 04 '16 at 17:19
  • Thanks again. Hope your solution works with all timezone and with or without daylight time saving. Did you get a chance to check my other datetime/timezone question which is never answered. https://stackoverflow.com/questions/35807298/javascript-how-do-i-convert-utc-date-time-to-est-hours-using-pure-javascript Thanks for your help in advance. – JsLearner Apr 04 '16 at 18:10
  • Wow, 10 points for overly complicated code, e.g. `map(function(token) { return parseInt(token, 10); })` can be just `.map(Number)`, and what you're passing to the function aren't tokens, they're values. The *newInstance* function is increadible and inefficient. `scope` seems to be arguments. Function *localDateToUTC* is completely unnecessary, Dates **are** UTC, that function just copies the date as if `new Date(date)`. – RobG Apr 05 '16 at 02:01
  • Wow, 10 points for overly complicated code, e.g. `map(function(token) { return parseInt(token, 10); })` can be just `.map(Number)`, and what you're passing to the function aren't tokens, they're values. The *newInstance* function is increadible and inefficient. `scope` seems to be arguments. Function *localDateToUTC* is completely unnecessary, Dates **are** UTC. This even returns the wrong values, it doesn't allow for the timezone offset, the original values **aren't UTC**. – RobG Apr 05 '16 at 02:08
  • @JsLearner—please don't confuse complicated code with "good". This code assumes that the values are UTC when they aren't, has a very convoluted way of calling the Date constructor, doesn't allow for the available time zone offset and has a crazy way of "converting" to UTC values (which are directly available from all Date instances). Parsing the string, with offset, is 4 lines of plain code. Formatting it is 2. – RobG Apr 05 '16 at 03:03
0

The first step is to parse your original string. Do not remove the timezone offset since timezone names are not standardised, nor are their abbreviations. To parse "Mon March 28 2016 23:59:59 GMT -0600 (CENTRAL DAYLIGHT TIME)" you can use a function like the following.

You can then format a string based on the date, but you must keep the timezone as a string like "2016-03-29 05:59:59" will be treated as local by any implementation that is vaguely consistent with ISO 8601.

In most cases, "2016-03-29 05:59:59Z" will be treated as UTC as the joining "T" can be omitted by agreement (per ISO 8601).

// Parse date string in format:
// "Mon March 28 2016 23:59:59 GMT -0600 (CENTRAL DAYLIGHT TIME)"
function parseDate(s) {
  var months = {jan:0,feb:1,mar:2,apr:3,may:4,jun:5,
                jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};
  var b = s.split(/[\s:]/);
  // Calc offset in minutes
  // JS offsets are opposite sense to everyone else
  var offset = (b[8] < 0? 1 : -1) * (b[8].slice(1,3)*60 + +b[8].slice(-2));
  // Create UTC date
  return new Date(Date.UTC(b[3], months[b[1].toLowerCase().substr(0,3)],
                            b[2], b[4], +b[5] + offset, b[6]));
} 

// Format date as yyyy-mm-dd hh:mm:ssZ
// The timezone really should be included as this string will
// be treated as local if ISO 8601 rules are used (and the commonly are)
function formatDate(d) {
  function z(n){return (n<10?'0':'')+n}
  return d.getUTCFullYear() + '-' +
         z(d.getUTCMonth() + 1) + '-' +
         z(d.getUTCDate()) + ' ' +
         z(d.getUTCHours()) + ':' +
         z(d.getUTCMinutes()) + ':' +
         z(d.getUTCSeconds()) + 'Z';
}

var s = 'Mon March 28 2016 23:59:59 GMT -0600 (CENTRAL DAYLIGHT TIME)';
var d = parseDate(s);

document.write('<br>Original: ' + s + '<br>' +
               'Local   : ' + d + '<br>' + 
               'UTC     : ' + formatDate(d) + '<br>' +
               'ISO 8601: ' + d.toISOString());
body {
  font-family: courier, monospace;
  font-size: 75%;
  white-space: pre;
}
RobG
  • 142,382
  • 31
  • 172
  • 209
  • Of course you can format the local date as UTC. I simply converted a local date to a UTC date object by treating it as if it were UTC. You obviously have not tried to create a date field that accepts and returns a UTC date string. The controls are working with a "local" date but treating it as "UTC". – Mr. Polywhirl Apr 05 '16 at 03:54
  • @Mr.Polywhirl—I don't understand your comment. You can only convert a "local" date string if you know the offset. Creating a date field that accepts and returns strings with GMT or UTC values is trivial (even the above does that, just send an offset of +0000), but the OP asked for something that converts a string with a time zone offset (-0600 in this case) to UTC. That's what this answer does (for any provided offset in the OP format). – RobG Apr 05 '16 at 07:08