I have tried below code to detect if Daylight Saving is observed or not, but although it's on, it always says it's not observed.
var myDate = new Date();
document.write(myDate.getTimezoneOffset());
var rightNow = new Date();
var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
var temp = jan1.toUTCString();
var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
var june1 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0);
temp = june1.toUTCString();
var june2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);
var dst;
if (std_time_offset == daylight_time_offset) {
dst = "0"; // daylight savings time is NOT observed
} else {
dst = "1"; // daylight savings time is observed
}
It's currently returning me "not oberserved", no matter which way I am using. (Can't add all methods here as it will be too long question)
Hence, I just want to confirm:
Does that require any settings in my machine?
Is there any specific country you have to be in to get this observed?
That code seems really complicated for what it needs to do. Here's a simple function that makes the same assumption you do (that DST is not in effect on Jan 1st of the year) and detects whether DST is in effect for the given Date instance:
function isDST(dt) {
// Northern or southern hemisphere?
// NOTE: Assumes that Jan 1st (southern hemisphere) or July 1st (northern hemisphere) will be DST
// This may be a "good enough" assumption, but if not, you'll need to download timezone information
const jan1 = new Date(dt.getFullYear(), 0, 1);
const jul1 = new Date(dt.getFullYear(), 6, 1);
const ref = jan1.getTimezoneOffset() < jul1.getTimezoneOffset() ? jul1 : jan1;
return dt.getTimezoneOffset() !== ref.getTimezoneOffset();
}
console.log(isDST(new Date(2018, 6, 1))); // true (if July 1st is DST in your timezone)
console.log(isDST(new Date(2018, 1, 1))); // false (if Feb 1st is not DST in your timezone)
It takes advantage of the fact that getTimezoneOffset includes the DST offset if DST is in effect.
Of course, if a location should change the timezone it's in permanently between the two dates, it would give a false positive, but that's a relatively rare occurrence.
The OP has been modified since my original answer so that it no longer applies. T.J. has alternative code, but so as not to waste an answer, here's a similar function that:
Gets the timezone offset for 1 Jan and 1 Jul for the related year
Assumes DST is in force and returns true if either:
the place observes DST as for the southern hemisphere DST (i.e. Jan offset is less than Jul offset, noting that javascript offsets are the opposite sense of ISO and all other commonly used systems) and the offset is the same as for January
the place observes DST as for the northern hemisphere DST (same caveat as above) and the offset is the same as for July
For any other case (jan offset equals jul offset so no DST at all, or date offset is as for non–DST offset) the date must not be in DST
function inDST(inDate) {
var inOffset = inDate.getTimezoneOffset();
var janOffset = new Date(inDate.getFullYear(), 0, 1).getTimezoneOffset();
var julOffset = new Date(inDate.getFullYear(), 6, 1).getTimezoneOffset();
return (janOffset < julOffset && janOffset == inOffset) ||
(janOffset > julOffset && julOffset == inOffset);
}
// Just a helper for testing
function fDate(d) {
var z = n => (n < 10 ? '0' : '') + n;
return `${z(d.getDate())}-${d.toLocaleString(undefined, {month:'short'})}-${d.getFullYear()}`;
}
// Tests
[new Date(2018, 1, 2), // 2 Feb 2018
new Date(2018, 5, 30)] // 30 Jun 2018
.forEach(d =>
console.log(`${fDate(d)}: ${inDST(d)}`)
);
Related
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.
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).
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>
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" });
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);
}
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");
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);
So I know this has been discussed as a problem before, but I'm looking more for some useful input really. I'm writing a calendar, and needed to add dates, and I came across an earlier thread (Add days to JavaScript Date), but it raised more quetions than answers. So I went away to code my own, and I'm close. This is what I've got:
Date.prototype.add = function(period, value, ignoreDaylightSaving)
{
var Day = this.getDate();
var Month = this.getMonth();
var Year = this.getFullYear();
var Hours = this.getHours();
var Mins = this.getMinutes();
var Secs = this.getSeconds();
var MilliSecs = this.getMilliseconds();
var TestDate;
var IgnoreDS = false;
var TZOffset1 = 0;
var TZOffset2 = 0;
if (typeof(ignoreDaylightSaving) == "boolen")
{
IgnoreDS = ignoreDaylightSaving;
}
switch (period.toUpperCase())
{
case "D":
Day += value;
break;
case "M":
Month += value;
break;
case "Y":
Year += value;
break;
case "H":
Hours += value;
break;
case "N":
Mins += value;
break;
case "S":
Secs += value;
break;
case "MS":
MilliSecs += value;
}
// Standardise Daylight Saving cut off.
if (IgnoreDS == false)
{
TestDate = new Date(Year, Month, Day, Hours, Mins, Secs, MilliSecs);
TZOffset1 = this.getTimezoneOffset();
TZOffset2 = TestDate.getTimezoneOffset();
if (value > 0)
{
if (this > TestDate)
{
if (TZOffset1 == TZOffset2)
{
Hours += 1;
}
}
} else {
if (this < TestDate)
{
if (TZOffset1 == TZOffset2)
{
Hours -= 1;
}
}
}
}
return(new Date(Year, Month, Day, Hours, Mins, Secs, MilliSecs));
}
It relies on Javascript to do the calcs for me. Internally, Dates and Times are just numbers, so if you pass a set of values, whether they are in range or not, javascript just multiplies them all out to get the internal number. Only when you apply Date functions to that number will it be converted into a date we recognise.
So my logic:
* split down the Date into its components
* add the value you want to one of the components
* create a new date from the components.
I've tested it with leap years IE and Chrome.
Daylight Saving is another matter. In the UK, British Summer Time begins 1am 30 March 2014. If I set a date of 30 March 2014 00:59:00 and add 2 minutes, Chrome gives me '30 March 2014 00:01:00' (GMT Standard Time), but IE gives me '30 March 2014 02:01:00' (GMT Summer Time).
Both browsers effectively say "you can't have a time of 01:01 in the morning of 30 March 2014 as it doesn't exist". IE advances to the next time (in effect adjusting the clock), whereas Chrome simply knocks you back an hour and keeps you in GMT Standard Time. When Summer Time ends they do it the opposite way round - IE keeps you in Summer Time and Chrome adjusts the clock for you. I've coded around this for going from GMT Standard to GMT Summertime (see the block under Standardise Daylight Saving cut off comment).
It's hard to code around the inconsistency in moving from GMT Summertime to GMT Standard though. I even wrote some javascript to find the change over dates by going through each month, then day then hour. But IE gives a different hour to Chrome. The code:
Date.prototype.getDaylightSavingDate = function(year)
{
var DSStart = new Date();
var DSEnd = new Date();
var MonthLoop;
var d1 = new Date();
var d2 = new Date();
var ThreshholdTZOffsets = new Array();
var ThreshholdMonths = new Array();
var ThreshholdDays = new Array();
var ThreshholdHours = new Array();
var ThisTZOffset;
var PrevTZOffset;
var THCount;
THCount = 0;
for (DateLoop=0; DateLoop < 12; DateLoop++)
{
d1 = new Date(year, DateLoop, 1);
ThisTZOffset = d1.getTimezoneOffset();
d2 = new Date(year, DateLoop-1, 1)
PrevTZOffset = d2.getTimezoneOffset();
if (PrevTZOffset != ThisTZOffset)
{
ThreshholdMonths[THCount] = DateLoop-1;
ThreshholdTZOffsets[THCount] = ThisTZOffset;
THCount += 1;
}
PrevTZOffset = ThisTZOffset
}
for (DateLoop=0; DateLoop<ThreshholdMonths.length; DateLoop++)
{
for (DayLoop=1; DayLoop < 32; DayLoop++)
{
d1 = new Date(year, ThreshholdMonths[DateLoop], DayLoop);
ThisTZOffset = d1.getTimezoneOffset();
d2 = new Date(year, ThreshholdMonths[DateLoop], DayLoop-1);
PrevTZOffset = d2.getTimezoneOffset();
if (PrevTZOffset != ThisTZOffset)
{
ThreshholdDays[DateLoop] = DayLoop-1;
}
PrevTZOffset = ThisTZOffset
}
}
for (DateLoop=0; DateLoop<ThreshholdMonths.length; DateLoop++)
{
for (HourLoop=0; HourLoop < 23; HourLoop++)
{
d1 = new Date(year, ThreshholdMonths[DateLoop], ThreshholdDays[DateLoop], HourLoop, 0, 0);
ThisTZOffset = d1.getTimezoneOffset();
d2 = new Date(year, ThreshholdMonths[DateLoop], ThreshholdDays[DateLoop], HourLoop-1, 0, 0);
PrevTZOffset = d2.getTimezoneOffset();
if (PrevTZOffset != ThisTZOffset)
{
ThreshholdHours[DateLoop] = HourLoop;
}
PrevTZOffset = ThisTZOffset
}
}
if (ThreshholdHours.length == 2)
{
DSStart = new Date(year, ThreshholdMonths[0], ThreshholdDays[0], ThreshholdHours[0],0,0,0);
DSEnd = new Date(year, ThreshholdMonths[1], ThreshholdDays[1], ThreshholdHours[1],0,0,0);
return({start:DSStart,end:DSEnd})
}
}
If you call this routine in IE and debug it ThreshholdDays[0]=1, and ThreshholdDays[1]=2. In Chrome however it's the other way round: ThreshholdDays[0]=2, and ThreshholdDays[1]=1.
My HTML for calling the routines:
<!DOCTYPE HTML>
<html dir="ltr" lang="en-gb" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test Dates</title>
<script language="javascript" type="text/javascript" src="LIBS/general.js"></script>
</head>
<body>
<div>
<script language="javascript" type="text/javascript">
var d1 = new Date(2014, 9, 26, 2,1,0);
var d2 = d1.add("n", -2, true);
var ds1 = d1.getDaylightSavingDate(2014);
alert(ds1.start + ", " + ds1.end);
alert(d1 + ", " + d2 + ", " + (d2-d1));
</script>
</div>
</body>
</html>
Anybody think of another way of doing this without explicitly coding for each browser?
If you compare the local timezone offsets for a date in June with a date in January you can tell if DST applies.
South of the equator, where DST is used, January is always in DST, north of the equator, June is always in DST.
You can find the month, day, hour and minute that DST and standard time start by advancing the Date object through months, days, hours and minutes in turn, checking the difference in timezone offsets.
It is a busy function, but needs only be done once for any year in a calendar app.
The function getDST returns an Array with a Date object representing the first minute of standard time for the given year,
the first minute of DST for that year, and the offset difference in minutes.
(The second function returns the date and a message to appear on that date in a calendar)
The best way to test this kind of function is to change the timezone in your computer for as many timezones as you can stand, with use dst enabled.
function getDST(y){
y= y || new Date().getFullYear();
var D1= new Date(y, 0, 1), D2= new Date(y, 5, 1),
off1= D1.getTimezoneOffset(), off2= D2.getTimezoneOffset(),
diff= off2-off1;
if(diff=== 0) return ;
var stdTime= D1, dstTime= D2,
std1= 11, dst1= 5,
stdOffset= off1, dstOffset= off2,
isDst, isStd, one= 1;
if(diff>0){
diff*= -1;
stdOffset= off2;
dstOffset= off1;
std1= 5;
dst1= 11;
}
function isDst(D){
return D.getTimezoneOffset()=== dstOffset;
}
function isStd(D){
return D.getTimezoneOffset()=== stdOffset;
}
function edgeTz(D, m, check){
D.setMonth(m);
while(check(D)) D.setMonth(m--);
D.setMonth(D.getMonth()+1);
while(check(D)) D.setDate(D.getDate()-1);
one= 1;
while(!check(D)) D.setHours(one++);
D.setHours(D.getHours()-1);
one= 1;
while(!check(D)) D.setMinutes(one++);
return D;
}
stdTime= edgeTz(stdTime, std1, isStd);
dstTime= edgeTz(dstTime, dst1, isDst);
return [stdTime, dstTime, diff];
}
// local start time for standard and dst:
getDST(2014).join('\n');
//result for EST
Sun Nov 02 2014 02: 00: 00 GMT-0500(Eastern Daylight Time)
Sun Mar 09 2014 03: 00: 00 GMT-0400(Eastern Standard Time)
-60
//calendar note:
function tzReport(y){
var z= getDST(y);
var dstMsg, stdMsg, changeStd, changeDst,
stdTime= z[0], dstTime= z[1], diff= z[2];
changeStd= new Date(stdTime);
changeStd.setDate(changeStd.getDate()+1);
changeStd.setMinutes(changeStd.getMinutes()-diff);
stdMsg= 'Standard Time begins. At '+
changeStd.timeString()+', clocks return to '+stdTime.timeString()+'.';
changeDst= new Date(dstTime);
changeDst.setDate(changeDst.getDate()+1);
changeDst.setMinutes(changeDst.getMinutes()+diff);
dstMsg= 'DST begins. At '+changeDst.timeString()+
', clocks advance to '+dstTime.timeString()+'.';
return [[stdTime.toLocaleDateString(), stdMsg],
[dstTime.toLocaleDateString(), dstMsg]];
}
//Calendar notice: tzReport(2014).join('\n');
Sunday, November 02, 2014,
Standard Time begins.
At 3: 00 am, clocks return to 2: 00 am.
Sunday, March 09, 2014, DST begins.
At 2: 00 am, clocks advance to 3: 00 am.
I need to be able to get the correct timezoneOffset by using javascript, if a user has disabled "Automatically adjust time clock for Daylights saving time" on his or her computer.
For example if i turn on automatically adjust DST i get -420 in june, and -480 in January for Pacific Time zone.
However if i disable Automatically adjust DST i get -480 for both January and June.
Is there any way to correct this behavior so that i get the expected DST even if automatically adjust DST time is checked off?
This is a function I've used a little while back (source), hope this helps.
function TimezoneDetect(){
var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
var intMonth;
var intHoursUtc;
var intHours;
var intDaysMultiplyBy;
//go through each month to find the lowest offset to account for DST
for (intMonth=0;intMonth < 12;intMonth++){
//go to the next month
dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);
//To ignore daylight saving time look for the lowest offset.
//Since, during DST, the clock moves forward, it'll be a bigger number.
if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
intOffset = (dtDate.getTimezoneOffset() * (-1));
}
}
return intOffset;
}
To detect DST without using getTimezoneOffset use this:
var rightNow = new Date();
var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
var temp = jan1.toGMTString();
var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
var june1 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0);
temp = june1.toGMTString();
var june2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);
var dst;
if (std_time_offset == daylight_time_offset) {
dst = "0"; // daylight savings time is NOT observed
} else {
dst = "1"; // daylight savings time is observed
}
getTime() gives you milliseconds since January 1, 1970.
How can I get the milliseconds since January 1, 2012?
This is what I currently have:
var n = new Date()
var a = n.getTime()
console.log (a)
How about:
var diff = new Date() - new Date(2012, 0, 1); // diff is in milliseconds
for calculating differences including local time zone deviations, or
var diff = new Date() - Date.UTC(2012, 0, 1); // diff in ms
for more scientific solutions.
Note that months in Javascript are zero based.
var ms = +new Date() - new Date( '2012/01/01' )
or make that 2nd date object new Date( '2012/01/01 GMT' ) if desired
Here is an example:
http://dl.dropbox.com/u/56150009/html/SO8780297/example.htm
Sample output. Notice how the DurationGMT & DurationLocal are different. When doing comparisons with dates always use GMT.
Now: 1,326,054,979,124 ms (Sun, 08 Jan 2012 20:36:19 GMT)
Start1: 1,325,376,000,000 ms (Sun, 01 Jan 2012 00:00:00 GMT)
Start2: 1,325,376,000,000 ms (Sun, 01 Jan 2012 00:00:00 GMT)
Start3: 1,325,376,000,000 ms (Sun, 01 Jan 2012 00:00:00 GMT)
DurationGMT: 678,979,124 ms (Accurate method)
StartLocal1: 1,325,397,600,000 ms (Sun, 01 Jan 2012 06:00:00 GMT)
DurationLocal: 657,379,124 ms !!! Don't use this method
Here are three methods to get a GMT date, #3 would be what you want.
var now = new Date();
var startOfYear1 = createGMTDate1(2012, 0, 1, 0, 0, 0, 0);
var startOfYear2 = createGMTDate2(2012, 0, 1, 0, 0, 0, 0);
var startOfYear3 = createGMTDate3(2012, 0, 1, 0, 0, 0, 0);
var durationGMTMillis = now.getTime() - startOfYear1.getTime(); // accurate
var startOfYearLocal1 = new Date(2012, 0, 1, 0, 0, 0, 0);
var durationLocalMillis = now.getTime() - startOfYearLocal1.getTime(); // inaccurate
function createGMTDate1(year, month, date, hours, mins, secs, millis) {
var dateDefaultTz = new Date(year, month, date, hours, mins, secs, millis);
var localeTzGMTMillis = dateDefaultTz.getTime();
var localeTzGMTOffsetMillis = dateDefaultTz.getTimezoneOffset() * 60 * 1000;
var dateGMT = new Date(localeTzGMTMillis - localeTzGMTOffsetMillis);
return dateGMT;
}
function createGMTDate2(year, month, date, hours, mins, secs, millis) {
var dateGMT = new Date(0);
dateGMT.setUTCFullYear(year);
dateGMT.setUTCMonth(month);
dateGMT.setUTCDate(date);
dateGMT.setUTCHours(hours);
dateGMT.setUTCMinutes(mins);
dateGMT.setUTCSeconds(secs);
dateGMT.setUTCMilliseconds(millis);
return dateGMT;
}
function createGMTDate3(year, month, date, hours, mins, secs, millis) {
var dateGMT = new Date(Date.UTC(year, month, date, hours, mins, secs, millis));
return dateGMT;
}
As others have said, the solution is subtracting Date instances:
var ms = now - before;
This works because the - operator converts its operands to Number (ECMAScript Language Specification, Edition 5.1, section 11.6.2). The corresponding ToNumber algorithm checks if the object has a valueOf method, and calls it if it exists (sections 9.3, 9.1, and 8.12.8).
It now happens that the Date.prototype.valueOf() method, that Date instances inherit, returns the same value as Date.prototype.getTime() for a given Date instance (section 15.9.5.8). Which is the number of milliseconds since January 1, 1970 (CE) 00:00:00.000 UTC ("epoch") (section 15.9.1.1).
The first operand is obvious if you want to compare against the local time:
var now = new Date();
The second part is a bit more tricky because you want to count from January 1, 2012 (CE) 00:00:00.000 GMT. For that you cannot use
var before = new Date(2012, 0, 1);
(or variations thereof) because it uses 00:00:00.000 local time (section 15.9.3.1). There are at least two ways to make this work:
Use a string value in a date format that must be recognized by conforming implementations of ECMAScript Edition 5.1 (section 15.9.1.15):
var ms = new Date() - new Date("2012-01-01T00:00:00.000Z");
If you are concerned about backwards compatibility, you can set the time explicitly (section 15.9.5):
var before = new Date();
before.setUTCFullYear(2012, 0, 1);
before.setUTCHours(0, 0, 0, 0);
var ms = now - before;
In an JS app, I receive timestamp (eq. 1270544790922) from server (Ajax).
Basing on that timestamp I create Date object using:
var _date = new Date();
_date.setTime(1270544790922);
Now, _date decoded timestamp in current user locale time zone. I don't want that.
I would like _date to convert this timestamp to current time in city of Helsinki in Europe (disregarding current time zone of the user).
How can I do that?
A Date object's underlying value is actually in UTC. To prove this, notice that if you type new Date(0) you'll see something like: Wed Dec 31 1969 16:00:00 GMT-0800 (PST). 0 is treated as 0 in GMT, but .toString() method shows the local time.
Big note, UTC stands for Universal time code. The current time right now in 2 different places is the same UTC, but the output can be formatted differently.
What we need here is some formatting
var _date = new Date(1270544790922);
// outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me
_date.toLocaleString('fi-FI', { timeZone: 'Europe/Helsinki' });
// outputs > "6.4.2010 klo 12.06.30"
_date.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' });
// outputs > "4/6/2010, 12:06:30 PM"
This works but.... you can't really use any of the other date methods for your purposes since they describe the user's timezone. What you want is a date object that's related to the Helsinki timezone. Your options at this point are to use some 3rd party library (I recommend this), or hack-up the date object so you can use most of it's methods.
Option 1 - a 3rd party like moment-timezone
moment(1270544790922).tz('Europe/Helsinki').format('YYYY-MM-DD HH:mm:ss')
// outputs > 2010-04-06 12:06:30
moment(1270544790922).tz('Europe/Helsinki').hour()
// outputs > 12
This looks a lot more elegant than what we're about to do next.
Option 2 - Hack up the date object
var currentHelsinkiHoursOffset = 2; // sometimes it is 3
var date = new Date(1270544790922);
var helsenkiOffset = currentHelsinkiHoursOffset*60*60000;
var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms]
var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset);
// Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT)
It still thinks it's GMT-0700 (PDT), but if you don't stare too hard you may be able to mistake that for a date object that's useful for your purposes.
I conveniently skipped a part. You need to be able to define currentHelsinkiOffset. If you can use date.getTimezoneOffset() on the server side, or just use some if statements to describe when the time zone changes will occur, that should solve your problem.
Conclusion - I think especially for this purpose you should use a date library like moment-timezone.
To account for milliseconds and the user's time zone, use the following:
var _userOffset = _date.getTimezoneOffset()*60*1000; // user's offset time
var _centralOffset = 6*60*60*1000; // 6 for central time - use whatever you need
_date = new Date(_date.getTime() - _userOffset + _centralOffset); // redefine variable
Just another approach
function parseTimestamp(timestampStr) {
return new Date(new Date(timestampStr).getTime() + (new Date(timestampStr).getTimezoneOffset() * 60 * 1000));
};
//Sun Jan 01 2017 12:00:00
var timestamp = 1483272000000;
date = parseTimestamp(timestamp);
document.write(date);
Cheers!
I have a suspicion, that the Answer doesn't give the correct result. In the question the asker wants to convert timestamp from server to current time in Hellsinki disregarding current time zone of the user.
It's the fact that the user's timezone can be what ever so we cannot trust to it.
If eg. timestamp is 1270544790922 and we have a function:
var _date = new Date();
_date.setTime(1270544790922);
var _helsenkiOffset = 2*60*60;//maybe 3
var _userOffset = _date.getTimezoneOffset()*60*60;
var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset);
When a New Yorker visits the page, alert(_helsenkiTime) prints:
Tue Apr 06 2010 05:21:02 GMT-0400 (EDT)
And when a Finlander visits the page, alert(_helsenkiTime) prints:
Tue Apr 06 2010 11:55:50 GMT+0300 (EEST)
So the function is correct only if the page visitor has the target timezone (Europe/Helsinki) in his computer, but fails in nearly every other part of the world. And because the server timestamp is usually UNIX timestamp, which is by definition in UTC, the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT), we cannot determine DST or non-DST from timestamp.
So the solution is to DISREGARD the current time zone of the user and implement some way to calculate UTC offset whether the date is in DST or not. Javascript has not native method to determine DST transition history of other timezone than the current timezone of user. We can achieve this most simply using server side script, because we have easy access to server's timezone database with the whole transition history of all timezones.
But if you have no access to the server's (or any other server's) timezone database AND the timestamp is in UTC, you can get the similar functionality by hard coding the DST rules in Javascript.
To cover dates in years 1998 - 2099 in Europe/Helsinki you can use the following function (jsfiddled):
function timestampToHellsinki(server_timestamp) {
function pad(num) {
num = num.toString();
if (num.length == 1) return "0" + num;
return num;
}
var _date = new Date();
_date.setTime(server_timestamp);
var _year = _date.getUTCFullYear();
// Return false, if DST rules have been different than nowadays:
if (_year<=1998 && _year>2099) return false;
// Calculate DST start day, it is the last sunday of March
var start_day = (31 - ((((5 * _year) / 4) + 4) % 7));
var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0));
// Calculate DST end day, it is the last sunday of October
var end_day = (31 - ((((5 * _year) / 4) + 1) % 7))
var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0));
// Check if the time is between SUMMER_start and SUMMER_end
// If the time is in summer, the offset is 2 hours
// else offset is 3 hours
var hellsinkiOffset = 2 * 60 * 60 * 1000;
if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset =
3 * 60 * 60 * 1000;
// Add server timestamp to midnight January 1, 1970
// Add Hellsinki offset to that
_date.setTime(server_timestamp + hellsinkiOffset);
var hellsinkiTime = pad(_date.getUTCDate()) + "." +
pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() +
" " + pad(_date.getUTCHours()) + ":" +
pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds());
return hellsinkiTime;
}
Examples of usage:
var server_timestamp = 1270544790922;
document.getElementById("time").innerHTML = "The timestamp " +
server_timestamp + " is in Hellsinki " +
timestampToHellsinki(server_timestamp);
server_timestamp = 1349841923 * 1000;
document.getElementById("time").innerHTML += "<br><br>The timestamp " +
server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp);
var now = new Date();
server_timestamp = now.getTime();
document.getElementById("time").innerHTML += "<br><br>The timestamp is now " +
server_timestamp + " and the current local time in Hellsinki is " +
timestampToHellsinki(server_timestamp);
And this print the following regardless of user timezone:
The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30
The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23
The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31
Of course if you can return timestamp in a form that the offset (DST or non-DST one) is already added to timestamp on server, you don't have to calculate it clientside and you can simplify the function a lot. BUT remember to NOT use timezoneOffset(), because then you have to deal with user timezone and this is not the wanted behaviour.
Presuming you get the timestamp in Helsinki time, I would create a date object set to midnight January 1 1970 UTC (for disregarding the local timezone settings of the browser).
Then just add the needed number of milliseconds to it.
var _date = new Date( Date.UTC(1970, 0, 1, 0, 0, 0, 0) );
_date.setUTCMilliseconds(1270544790922);
alert(_date); //date shown shifted corresponding to local time settings
alert(_date.getUTCFullYear()); //the UTC year value
alert(_date.getUTCMonth()); //the UTC month value
alert(_date.getUTCDate()); //the UTC day of month value
alert(_date.getUTCHours()); //the UTC hour value
alert(_date.getUTCMinutes()); //the UTC minutes value
Watch out later, to always ask UTC values from the date object. This way users will see the same date values regardless of local settings.
Otherwise date values will be shifted corresponding to local time settings.
My solutions is to determine timezone adjustment the browser applies, and reverse it:
var timestamp = 1600913205; //retrieved from unix, that is why it is in seconds
//uncomment below line if you want to apply Pacific timezone
//timestamp += -25200;
//determine the timezone offset the browser applies to Date()
var offset = (new Date()).getTimezoneOffset() * 60;
//re-initialize the Date function to reverse the timezone adjustment
var date = new Date((timestamp + offset) * 1000);
//here continue using date functions.
This point the date will be timezone free and always UTC, You can apply your own offset to timestamp to produce any timezone.
Use this and always use UTC functions afterwards e.g. mydate.getUTCHours();
function getDateUTC(str) {
function getUTCDate(myDateStr){
if(myDateStr.length <= 10){
//const date = new Date(myDateStr); //is already assuming UTC, smart - but for browser compatibility we will add time string none the less
const date = new Date(myDateStr.trim() + 'T00:00:00Z');
return date;
}else{
throw "only date strings, not date time";
}
}
function getUTCDatetime(myDateStr){
if(myDateStr.length <= 10){
throw "only date TIME strings, not date only";
}else{
return new Date(myDateStr.trim() +'Z'); //this assumes no time zone is part of the date string. Z indicates UTC time zone
}
}
let rv = '';
if(str && str.length){
if(str.length <= 10){
rv = getUTCDate(str);
}else if(str.length > 10){
rv = getUTCDatetime(str);
}
}else{
rv = '';
}
return rv;
}
console.info(getDateUTC('2020-02-02').toUTCString());
var mydateee2 = getDateUTC('2020-02-02 02:02:02');
console.info(mydateee2.toUTCString());
// you are free to use all UTC functions on date e.g.
console.info(mydateee2.getUTCHours())
console.info('all is good now if you use UTC functions')