MomentJS: Compare time in different timezones - node.js

I have array of timezones and I want to know which one is the 'earliest one' where earliest is the one in the earliest time zone.
For example:
Timezone X is Thursday 5pm
Timezone Y is Thursday 7pm
Than X is the earliest among them.
I'm using momentjs and momentjs-timzone in NodeJS (not the browser package)
I'm trying to compare the millisecond timestamp but this give me the same value for both:
if (momenttz().tz(timezoneX).format('x') > momenttz().tz(timezoneY).format('x'))

In NodeJS syntax it can accomplished by formatting timezones to offset values, finding the minimum component and returning its Timezone value:
var moment = require('moment-timezone');
var inputTzArray = ['Pacific/Chatham', 'America/St_Johns', 'Asia/Jerusalem', 'America/New_York', 'America/Los_Angeles'];
var tzOffsets = []
for (var i in inputTzArray) {
var s = moment.tz(inputTzArray[i]).format('Z'); //format to offset
tzOffsets[i] = parseFloat(s.replace(':','.')); //parse int offset
}
console.log(tzOffsets);
var minIndex = tzOffsets.indexOf(Math.min.apply(Math, tzOffsets)); //find minimum's index
console.log(inputTzArray[minIndex]); //Output earliest timezone
A live demo by running "node server.js" in the interactive console in the link: http://runnable.com/VJ3M3XdZAVg-EVOP

Related

Convert user define time to UTC using moment

We have application where we ask user to define time when they want to publish some content. In our application, user will select that content should publish X(0-5) day before target date and y time (0-23).
So if user create a content with publish date = "09/21/2021" and publish time as 3 it means this content needs to publish at 3 AM on 09/21/2021.
In our Mongo DB we need to store the calculated date as "2021-09-21T07:00:00" So it can be pulled by our Cron Job.
We tried will following without any success
var promotedDate = "2021-08-19 04:00:00"
var fmt = "YYYY-MM-DD hh:mm:ss";
var m = moment.utc(promotedDate, fmt);
console.log('promoted date ', tempDate)
console.log(m.local().format(fmt));
console.log(m.utc().format(fmt));
But it gives 2021-08-19 12:00:00
Any help ?
You can use moment.toISOString(). That will give you UTC regardless of the timezone of the moment in question thus: 2013-02-04T22:44:30.652Z.
Since that comes with milliseconds and a Z for Zulu time, we need to strip off the last 5 characters with string.slice():
const promotedDate = "2021-08-19 04:00:00";
const m = moment.utc(promotedDate, "YYYY-MM-DD hh:mm:ss");
const iso8601 = m.toISOString()
.slice(0,-5); // removes milliseconds and `Z` for Zulu
console.log( `promoted: ${promotedDate}` );
console.log( `iso8601: ${iso8601} );

Return new date after adding the number to the today's date in node js

I have a logical question may be it sound simple but I am facing problem while solving this. Situation is I have a number of days that is expire days now by using that number I have to create a expire date, let me give you one example.
if today's date is 25-07-2020 and no.of expire days is 10 then expire date should be 04-08-2020
I want to this to implement in node js, right now I am getting today's date using Date method.
const today = new Date().toISOString().replace(/\T.+/, '')
This returns today's date but now I am confused how can I get my expire date after adding no.of days.
You need to use setDate here
var currentDate = new Date();
currentDate.setDate(currentDate.getDate() + 10);
console.log(currentDate) //this will have the new date
You can do this with a function:
function addDays(date, days) {
const copy = new Date(Number(date))
copy.setDate(date.getDate() + days)
return copy
}
const date = new Date();
const newDate = addDays(date, 10);
So, you can't add 10 days by simple manipulation of the Date as a string, since you'd need to account for all sorts of edge cases (change of month, change of year, time-zone changes).
There are lots of good libraries out there that can help you, like date-fns or Moment.js.
However, if you want to do this without a library, it's quite straightforward:
const now = +new Date(); // Gets the date as ms since epoch
const expiry = new Date(now + (10 * 24 * 60 * 60 * 1000)); Adds 10 days worth of ms

How to set timezone with moment?

i am using moment for getting server time .
moment.tz.setDefault("Asia/Kolkata");
var now = new Date();
var _p_date = moment.tz(now, zone).format();
time when inserting _p_date = 2016-01-05T18:32:00+05:30
But in database date variable is type of DATETIME. and time is saved as 2016-01-05 18:32:00.
and after that when i comparing with this to get time_ago funcionality. providing me wrong estimation.
using time ago = moment("2016-01-05T18:32:00.000Z").fromNow(); // is showing In 5 hours
Since your initial timezone is lost you have to create moment.tz object with selected timezone. Try this plunker
var date = moment.tz(moment("2016-01-05T18:32:00.000Z", "YYYY-MM-DDTHH:mm")
.format('YYYY-MM-DD HH:mm'), 'Asia/Kolkata');
console.log(date.fromNow());

How to determine two date is same day at local time in nodejs?

Here are two date, 2015-11-10 09:00:00+08:00 and 2015-11-10 01:00:00+08:00 is same day in China. But they are different day in UTC.
So... How can I determine two UTC date is same day at different timezone in node.js?
Sorry for my ambiguous description and poor English.
I have two strings: start_time and end_time. And clint upload two other strings: timezone_str, utc_time_str.
I want to determine the client time is between start and end time.
e.g
start_time: 2015-11-10 00:00:00
end_time: 2015-11-11 00:00:00
utc_time_str: 2015-11-10 02:00:00Z
timezone_str: America/New_York
except client_time.isBetween(start_time, end_time) == false.
Thanks to #Matt Johnson's answer, moment-timezone can solve my problem.
client_time = moment(utc_time_str).tz(timezone_str);
start = moment.tz(start_time, timezone_str);
end = moment.tz(end, timezone_str);
client_time.isBetween(start, end) === false
The most reliable way would be to use the parseZone function in moment.js to retain the provided offset. Then use the isSame function with the 'day' argument, which tests for same year, month, and day.
var m1 = moment.parseZone("2015-11-10 09:00:00+08:00");
var m2 = moment.parseZone("2015-11-10 01:00:00+08:00");
if (m1.isSame(m2, 'day')) {
// ...
}
With this approach, it does not matter what offset was given, nor does it matter what the time zone is on the computer where the code is running. It simply compares the two dates as provided.
calculate local "hours" like this
var d1 = new Date('2015-11-10 09:00:00+08:00')
var d2 = new Date('2015-11-10 01:00:00+08:00')
var h1 = d1.getHours() - d1.getTimezoneOffset() / 60
var h2 = d2.getHours() - d2.getTimezoneOffset() / 60
var date1 = d1.getDate() + (h1 >= 24? 1: 0)
var date2 = d2.getDate() + (h2 >= 24? 1: 0)
just compare date1 and date2
Solution without MomentJS
If you have the timezone string of the user that is in accordance with the tz database, such as "America/New_York" — which you can get client side for example by doing: const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
Then you could, for each date, create a new date with the timezone offset added to the original date, for example by doing const dateInTimezone = new Date(new Date(myDate).toLocaleString("en-US", { timeZone: timezone }));
And then reset the time values to exactly midnight of the same day by doing dateInTimezone.setHours(0, 0, 0, 0);
Then you could compare the milliseconds since Epoch values (date we start counting UTC from) of the two dates to see whether they start in the same day or not: const isSameDay = startOfDate1.valueOf() === startOfDate2.valueOf();
Ideally, your starting dates would always be in UTC, since both your server and client could be in all sorts of timezones. So before storing the data, convert the original date to its UTC version in milliseconds since Epoch, by doing myOrignalDate.valueOf() or myOrignalDate.getTime() — this way, you will ensure that timezone offsets added later will be true.
Example
function isSameDayInTimezone(d1, d2, timezone) {
const start_of_d1 = new Date(new Date(d1).toLocaleString("en-US", { timeZone: timezone })).setHours(0, 0, 0, 0).valueOf();
const start_of_d2 = new Date(new Date(d2).toLocaleString("en-US", { timeZone: timezone })).setHours(0, 0, 0, 0).valueOf();
return start_of_d1 === start_of_d2;
}
/* Initialize dates. Note that this will be the UTC time as milliseconds since
Epoch of the date in whichever timezone it was originally captured in. If I
capture it in my timezone, it would currently be UTC/GMT+3, hence if I were
to want to perform server-side actions taking into account my timezone, I'd
also need to capture my tz database timezone string first, to then be able
to, server-side, add my timezone offset to the captured UTC time. */
const date1 = new Date('August 31, 2022 20:16:00').valueOf();
const date2 = new Date('August 31, 2022 23:50:00').valueOf();
const date3 = new Date('August 31, 2022 00:00:00').valueOf();
const date4 = new Date('August 30, 2022 15:00:00').valueOf();
const fixedTimezone = "Europe/Tallinn";
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
/* With fixed timezone */
console.log(isSameDayInTimezone(date1, date2, fixedTimezone));
console.log(isSameDayInTimezone(date1, date3, fixedTimezone));
console.log(isSameDayInTimezone(date1, date4, fixedTimezone));
/* With local timezone */
console.log(isSameDayInTimezone(date1, date2, localTimezone));
console.log(isSameDayInTimezone(date1, date3, localTimezone));
console.log(isSameDayInTimezone(date1, date4, localTimezone));
Voila, no MomentJS needed.

How do I display todays date in Node.js Jade?

I am new to Node.js and Jade and I have tried to use #{Date.now()} and it's giving me numbers. How do I display the date in mm/dd/yy format?
You can use moment.js
First, add moment to your express application locals
express = require('express');
...
app = express();
app.locals.moment = require('moment');
Then you can use moment within a jade template like this:
p #{moment(Date.now()).format('MM/DD/YYYY')}
Moment takes Date.now() by default, so yo can also write:
p #{moment().format('MM/DD/YYYY')}
Sources:
Making use of utility libraries in server-side Jade templates
Moment.js
This is old, but I do the following:
return (new Date()).toLocaleDateString()
Returns a date 'mm/dd/yyyy' format, in no additional libs required.
Or you could use the moment.js library to handle dates and format them accordingly to your needs
I actually started using date-util which is 2 parts both clientside and server side.
URL https://github.com/JerrySievert/node-date-utils
Using within a Browser
<script type="text/javascript" src="date-utils.min.js"></script>
Using with Node.js
$ npm install date-utils
require('date-utils');
Note: This did not work in the REPL before Node.js 0.6 due to how Node.js handles context in the REPL.
Static Methods
Date.today(); // today, 00:00:00
Date.yesterday(); // yesterday, 00:00:00
Date.tomorrow(); // tomorrow, 00:00:00
Date.validateDay(day, year, month); // true/false whether a date is valid
Date.validateYear(year); // true/false whether a year is valid
Date.validateMonth(month); // true/false whether a month is valid
Date.validateHour(hour); // true/false whether an hour is valid
Date.validateMinute(minute); // true/false whether a minute is valid
Date.validateSecond(second); // true/false whether a second is valid
Date.validateMillisecond(millisecond); // true/false whether a millisecond is valid
Date.compare(date1, date2); // -1 if date1 is smaller than date2, 0 if equal, 1 if date2 is smaller than date1
Date.equals(date1, date2); // true/false if date1 is equal to date2
Date.getDayNumberFromName(name); // su/sun/sunday - 0, mo/mon/monday - 1, etc
Date.getMonthNumberFromName(name); // jan/january - 0, feb/february - 1, etc
Date.isLeapYear(year); // true/false whether the year is a leap year
Date.getDaysInMonth(monthNumber); // number of days in the month
Instance Methods
d.clone(); // returns a new copy of date object set to the same time
d.getMonthAbbr(); // abreviated month name, Jan, Feb, etc
d.getMonthName(); // fill month name, January, February, etc
d.getUTCOffset(); // returns the UTC offset
d.getOrdinalNumber(); // day number of the year, 1-366 (leap year)
d.clearTime(); // sets time to 00:00:00
d.setTimeToNow(); // sets time to current time
d.toFormat(format); // returns date formatted with:
// YYYY - Four digit year
// MMMM - Full month name. ie January
// MMM - Short month name. ie Jan
// MM - Zero padded month ie 01
// M - Month ie 1
// DDDD - Full day or week name ie Tuesday
// DDD - Abbreviated day of the week ie Tue
// DD - Zero padded day ie 08
// D - Day ie 8
// HH24 - Hours in 24 notation ie 18
// HH - Padded Hours ie 06
// H - Hours ie 6
// MI - Padded Minutes
// SS - Padded Seconds
// PP - AM or PM
// P - am or pm
d.toYMD(separator); // returns YYYY-MM-DD by default, separator changes delimiter
d.between(date1, date2); // true/false if the date/time is between date1 and date2
d.compareTo(date); // -1 if date is smaller than this, 0 if equal, 1 if date is larger than this
d.equals(date); // true/false, true if dates are equal
d.isBefore(date); // true/false, true if this is before date passed
d.isAfter(date); // true/false, true if this is after date passed
d.getDaysBetween(date); // returns number of full days between this and passed
d.getHoursBetween(date); // returns number of hours days between this and passed
d.getMinutesBetween(date); // returns number of full minutes between this and passed
d.getSecondsBetween(date); // returns number of full seconds between this and passed
d.add({ milliseconds: 30,
minutes: 1,
hours: 4,
seconds: 30,
days: 2,
weeks: 1,
months: 3,
years: 2}); // adds time to existing time
d.addMilliseconds(number); // add milliseconds to existing time
d.addSeconds(number); // add seconds to existing time
d.addMinutes(number); // add minutes to existing time
d.addHours(number); // add hours to existing time
d.addDays(number); // add days to existing time
d.addWeeks(number); // add weeks to existing time
d.addMonths(number); // add months to existing time
d.addYears(number); // add years to existing time
You will need to use the methods on the Date object to achieve what you're after. See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date
For example, the code below should do what you need:
var dateNow = new Date();
var dd = dateNow.getDate();
var monthSingleDigit = dateNow.getMonth() + 1,
mm = monthSingleDigit < 10 ? '0' + monthSingleDigit : monthSingleDigit;
var yy = dateNow.getFullYear().toString().substr(2);
var formattedDate = mm + '/' + dd + '/' + yy;
So if you were using say jade with express and node you could do something like:
res.render('jadeTemplateName', {
dateNow: function() {
var dateNow = new Date();
var dd = dateNow.getDate();
var monthSingleDigit = dateNow.getMonth() + 1,
mm = monthSingleDigit < 10 ? '0' + monthSingleDigit : monthSingleDigit;
var yy = dateNow.getFullYear().toString().substr(2);
return (mm + '/' + dd + '/' + yy);
}
})
and in your jade template say if you wanted to add the date to a span:
span Today's date is #{dateNow()}
add the class .post-date to a tag holding the date
document.addEventListener('DOMContentLoaded', function() {
var list = document.getElementsByClassName('post-date');
// get the number of selected elements
// iterate over elements and output their HTML content
for (var i=0; i<list.length; i++){
//console.log(list[i].innerHTML);
var string=list[i].innerHTML;
var length = 15;
var trimmedString = string.substring(0, length);
list[i].innerHTML=trimmedString ;
}
})
I found a solution
1.Create a function in pug using - syntax
2.pass the varible to the function when pug.js is binding variables to the pug template
-function prettyDate(dateString){
-var date = new Date(dateString);
-var d = date.getDate();
-var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
-var m = monthNames[date.getMonth()];
-var y = date.getFullYear();
-return d+' '+m+' '+y;
-}
3.span.post-date #{prettyDate(val.date)};

Resources