M21
M21

Reputation: 343

Date - specific time each day, specific timezone

** UPDATE**

using moment.js would be ok if that would make it easier? all I'm wanting to do is display a countdown timer that count down to 3pm PST (6EST) daily.


Looking for a way to have javascript get new Date() to use a specific time zome, not the user's time.

I have:

function ShowTime()  {
  var now = new Date();
  var hrs = 14-now.getHours();
  var mins = 59-now.getMinutes();
  var secs = 59-now.getSeconds();
      timeLeft etc etc...

jsfiddle (works) but I think it's my own machine's time: http://jsfiddle.net/36sqeq8x/

still not working... I just need to count down to 3pm PST (6EST) daily... without trying to calculate it on users end based on their time zone, like if could calculate from GMT, that would potentially work? but is that even possible.

maybe a combination of something like this? https://jsfiddle.net/salman/PxzJu/

Upvotes: 0

Views: 319

Answers (3)

RobG
RobG

Reputation: 147453

One way to go about this is to create a Date for the current date and 15:00 in time zone GMT-0800. If that's already passed, add a day to it. If it's more than 1 day in the future (unlikely in a time zone so far west) then subtract a day.

Then subtract the current time from that to get the milliseconds to the next 15:00 PST.

The following makes use of some helper functions, the largest is parseISO to parse an ISO 8601 date string to avoid parsing by the built–in Date parser. toISODate is used to build a string for 15:00 PDT, the others are just for output. Hopefully the documentation and comments is sufficient.

// Create a date for the current date at 15:00 PST (UTC-0800)
// Current date and time
var dLocal = new Date();
// Create Date for same date but time 15:00 at UTC-0800
var dPST  = parseISO(toISODate(dLocal) + 'T' + '15:00:00-0800');

// If dPST has passed, add a day
if (dPST < dLocal) dPST.setDate(dPST.getDate() + 1);
// If gap is too big, subtract a day
if (dPST - dLocal > 8.64e7) dPST.setDate(dPST.getDate() - 1);

console.log('Current local: '   + toISOString(dLocal) + 
            '\nCurrent PST:   ' + toISOStringOffset(-480, dLocal) + 
            '\nNext 3pm PST in PST zone: ' + toISOStringOffset(-480, dPST) +
            '\nNext 3pm PST in local zone: ' + toISOString(dPST) +
            '\nms to 3pm PST: ' + (dPST - dLocal)
);



/* Parse ISO date string in format yyyy-mm-ddThh:mm:ss.sss+hh:mm or Z
** @param (string} s - string to parse in ISO 8601 extended format
**                     yyyy-mm-ddThh:mm:ss.sss+/-hh:mm or z
**                     time zone can omit separator, so +05:30 or +0530
** @returns {Date}   - returns a Date object. If any value out of range,
**                     returns an invalid date.
*/
function parseISO(s) {
  // Create base Date object
  var date = new Date();
  var invalidDate = new Date(NaN);
  // Set some defaults
  var sign = -1, tzMins = 0;
  var tzHr, tzMin;
  // Trim leading and trailing whitespace
  s = s.replace(/^\s*|\s*$/g,'').toUpperCase();
  // Get parts of string and split into numbers
  var d  = (s.match(/^\d+(-\d+){0,2}/)             || [''])[0].split(/\D/);
  var t  = (s.match(/[\sT]\d+(:\d+){0,2}(\.\d+)?/) || [''])[0].split(/\D/);
  var tz = (s.match(/Z|[+\-]\d\d:?\d\d$/)          || [''])[0];

  // Resolve timezone to minutes, may be Z, +hh:mm or +hhmm
  // Splitting into parts makes validation easier
  if (tz) {
    sign  = /^-/.test(tz)? 1 : -1;
    tzHr  = tz == 'Z'? 0 : tz.substr(1,2);
    tzMin = tz == 'Z'? 0 : tz.substr(tz.length - 2, 2)*1;
    tzMins = sign * (tzHr*60 + tzMin);
  }

  // Validation
  function isLeap(year){return year % 4 != 0 || year % 100 == 0 && year % 400 != 0}
  // Check number of date parts and month is valid
  if (d.length > 3 || d[1] < 1 || d[1] > 12) return invalidDate;
  // Test day is valid
  var monthDays = [,31,28,31,30,31,30,31,31,30,31,30,31];
  var monthMax = isLeap(d[0]) && d[1] == 2? 29 : monthDays[d[1]];
  if (d[2] < 1 || d[1] > monthMax) return invalidDate;
  // Test time parts
  if (t.length > 5 || t[1] > 23 || t[2] > 59 || t[3] > 59 || t[4] > 999) return invalidDate;
  // Test tz within bounds
  if (tzHr > 12 || tzMin > 59) return invalidDate;

  // If there's a timezone, use UTC methods, otherwise local
  var method = tz? 'UTC' : '';
  
  // Set date values
  date['set' + method + 'FullYear'](d[0], (d[1]? d[1]-1 : 0), d[2]||1);
  // Set time values - first memeber is '' from separator \s or T
  date['set' + method + 'Hours'](t[1] || 0, (+t[2]||0) + tzMins, t[3]||0, t[4]||0);

  return date;
}

/* Return ISO 8601 formatted string with local offset, e.g. 2016-06-12T12:43:23.432+05:30
** @param {Date} d - date to craete string from
** @returns {string} in ISO 8601 format with offset
*/
function toISOString(d) {
  d = d || new Date();
  var offset = d.getTimezoneOffset();
  function z(n){return (n<10?'0':'') + n}
  // Reverse signe of offset to be consistent with ISO 8601
  var offSign = offset < 0? '+' : '-';
  offset = Math.abs(offset);
  var offHr  = z(offset/60 | 0);
  var offMin = z(offset%60);
  return d.getFullYear() + '-' + z(d.getMonth() + 1) + '-' + z(d.getDate()) + 'T' +
         z(d.getHours()) + ':' + z(d.getMinutes()) + ':' + z(d.getSeconds()) + '.' +
         ('00' + d.getMilliseconds()).slice(-3) + offSign + offHr + ':' + offMin;
}

/* Given a Date, return an ISO 8601 formatted date and time string
** for a particular time zone.
** @param {number} offset - offset in minutes +east, -west, default is local
** @param {Date} d - date to use, default is now
** @returns {string} ISO 8601 formatted string for supplied time zone offset
*/
function toISOStringOffset(offset, d) {
  // Copy date if supplied or use now
  d = d? new Date(+d) : new Date();
  // Prepare offset values
  offset = offset || -d.getTimezoneOffset();
  var offSign = offset < 0? '-' : '+'; 
  offset = Math.abs(offset);
  var offHours = ('0' + (offset/60 | 0)).slice(-2);
  var offMins  = ('0' + (offset % 60)).slice(-2);

  // Apply offset to d
  d.setUTCMinutes(d.getUTCMinutes() - offset);

  // Return formatted string
  return d.getUTCFullYear() + 
    '-' + ('0' + (d.getUTCMonth()+1)).slice(-2) + 
    '-' + ('0' + d.getUTCDate()).slice(-2) + 
    'T' + ('0' + d.getUTCHours()).slice(-2) + 
    ':' + ('0' + d.getUTCMinutes()).slice(-2) + 
    ':' + ('0' + d.getUTCSeconds()).slice(-2) + 
    '.' + ('000' + d.getUTCMilliseconds()).slice(-3) +
    offSign + offHours + ':' + offMins; 
}

/* Return an ISO 8601 formatted date string based on local time
** Year must be positive (i.e. doesn't do -ve year)
** @param {Date} date - date object to create date string from
** @returns {string} dates string in yyyy-mm-dd format or default from
**                   Date.prototype.toString (i.e. "Invalid Date")
*/
function toISODate(date) {
  return date.getDate()? ('000' + date.getFullYear()).slice(-4) + '-' +
                         ('0' + (date.getMonth() + 1)).slice(-2) + '-' +
                         ('0' + date.getDate()).slice(-2) : date.toString();
}

Upvotes: 1

ManoDestra
ManoDestra

Reputation: 6483

You can use the getUTCHours() and setUTCHours() functions on a date to get/set the hours based on UTC hours instead of local hours. E.g.

var date = new Date();
date.setUTCHours(5);

Or, better, you can use the getTimezoneOffset() function to show the difference and calculate and adjust back to UTC, or which ever timezone you desire. NB the offset is returned in MINUTES.

var date = new Date();
var offset = date.getTimezoneOffset();
console.log(offset);

My output to the above is 300, as I am in CST (strictly speaking, CDT) which is currently 5 hours behind UTC.

Upvotes: 0

Gerardo Furtado
Gerardo Furtado

Reputation: 102198

The setUTCHours() method sets the hour of a date object, according to the UTC time.

var d = new Date();
d.setUTCHours(15);

Here is the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCHours

Alternatively, getUTChours return the hour, according to universal time:

var d = new Date();
var n = d.getUTCHours();

Here is the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getUTCHours

Upvotes: 0

Related Questions