10

I have a challenge where backend data is always stored in UTC time. Our front-end data is always presented in CST. I don't have access to this 'black box.'

I would like to mirror this in our data warehouse. Which is based in Europe (CET). So "local" conversion will not work.

I'm wondering the simplest, most straightforward way to accurately convert UTC time (I can have it in epoch milliseconds or a date format '2015-01-01 00:00:00') to Central Standard Time. (which is 5 or 6 hours behind based on Daylight Savings).

I see a lot of threads about converting to 'local' time ... again I don't want this, nor do I simply want to subtract 6 hours which will be wrong half the year.

Anyone have any ideas? This seems to be a very common problem but I've been searching for a while, and have found nothing.

user45867
  • 887
  • 2
  • 17
  • 30

6 Answers6

7

Using moment.js with the moment-timezone add-on makes this task simple.

// construct a moment object with UTC-based input
var m = moment.utc('2015-01-01 00:00:00');

// convert using the TZDB identifier for US Central time
m.tz('America/Chicago');

// format output however you desire
var s = m.format("YYYY-MM-DD HH:mm:ss");

Additionally, since you are referring to the entire North American Central time zone, you should say either "Central Time", or "CT". The abbreviation "CST" as applied to North America explicitly means UTC-6, while the "CDT" abbreviation would be used for UTC-5 during daylight saving time.

Do be careful with abbreviations though. "CST" might mean "China Standard Time". (It actually has five different interpretations).

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 3
    Moment is quite heavy and unnecessary for a simple task like this that you could totally do without moment – wa7d Sep 16 '19 at 04:57
5

You can use the time zone offset to determine whether 5 or 6 hours should be subtracted.

var dateJan;
var dateJul;
var timezoneOffset;

var divUTC;
var divCST;

// Set initial date value
dateValue = new Date('10/31/2015 7:29:54 PM');

divUTC = document.getElementById('UTC_Time');
divCST = document.getElementById('CST_Time');
divUTC.innerHTML = 'from UTC = ' + dateValue.toString();

// Get dates for January and July
dateJan = new Date(dateValue.getFullYear(), 0, 1);
dateJul = new Date(dateValue.getFullYear(), 6, 1);

// Get timezone offset
timezoneOffset = Math.max(dateJan.getTimezoneOffset(), dateJul.getTimezoneOffset());

// Check if daylight savings
if (dateValue.getTimezoneOffset() < timezoneOffset) {
  // Adjust date by 5 hours
  dateValue = new Date(dateValue.getTime() - ((1 * 60 * 60 * 1000) * 5));
}
else {
  // Adjust date by 6 hours
  dateValue = new Date(dateValue.getTime() - ((1 * 60 * 60 * 1000) * 6));
}

divCST.innerHTML = 'to CST = ' + dateValue.toString();
<div id="UTC_Time"></div>
<br/>
<div id="CST_Time"></div>
WhiteHat
  • 59,912
  • 7
  • 51
  • 133
  • hmm I will have to try this – user45867 Dec 18 '15 at 20:24
  • Nice try, but flawed. The `Date` object will only tell you if the *local* time zone is in DST or not. DST is not uniformly applied worldwide. – Matt Johnson-Pint Dec 18 '15 at 21:33
  • You're also interpreting the input value in the local time zone, not in UTC, and are using the locale-specific `MM/DD/YYYY` format in the string. Additionally, shifting the time itself is not the safest way to adjust for time zone. These errors are all too easy to make, especially in JavaScript. Take a good look at moment.js - it will make your life easier. Cheers! :) – Matt Johnson-Pint Dec 18 '15 at 21:41
1

Maybe you can use something like the following. Note, that is just an example you might need to adjust it to your needs.

    let cstTime = new Date(createdAt).toLocaleString("es-MX", {
    timeZone: "America/Mexico_City" });
Brenda Jimenez
  • 751
  • 1
  • 7
  • 12
0

You can use below code snippet for converting.

function convertUTCtoCDT() {
    var timelagging = 6; // 5 or 6
    var utc = new Date();
    var cdt = new Date(utc.getTime()-((1 * 60 * 60 * 1000) * timelagging));
    console.log("CDT: "+cdt);
}
Suneet Patil
  • 608
  • 9
  • 21
0
let newDate = moment(new Date()).utc().format("YYYY-MM-DD HH:mm:ss").toString()
var m = moment.utc(newDate);
m.tz('America/Chicago');
var cstDate = m.format("YYYY-MM-DD HH:mm:ss");
-1

You can use below code snippet

// Get time zone offset for CDT or CST
const getCdtCstOffset = () => {
  const getNthSunday = (date, nth) => {
      date.setDate((7*(nth-1))+(8-date.getDay()));
      return date;
  }
  const isCdtTimezoneOffset = (today) => {
    console.log('Today : ', today);
    let dt = new Date();
    var mar = new Date(dt.getFullYear(), 2, 1);
    mar = getNthSunday(mar, 2);
    console.log('CDT Start : ', mar);
    var nov = new Date(dt.getFullYear(), 10, 1, 23, 59, 59);
    nov = getNthSunday(nov, 1);
    console.log('CDT End : ', nov);
    return mar.getTime()< today.getTime() && nov.getTime()> today.getTime();
  }
  var today = new Date()// current date
  if (isCdtTimezoneOffset(today)) {
    return -5
  } else {
    return -6
  }
}
let cstOrCdt = new Date();
cstOrCdt.setHours(cstOrCdt.getHours()+getCdtCstOffset())
console.log('CstOrCdt : ', cstOrCdt);
Nilesh Patel
  • 127
  • 2
  • 9