Create a new Date for any specific timezone - javascript

I am using Google Apps Script to check and re-format date data from some Google Sheets. But the problem is the result shows the times for the user who run the code. I want to show the date for any specific time zone. How is it possible?
Suppose, my input is checkDate('14/5/2022'); and it returns the date
object for that time zone instead of my time zone.
Here is my code:
/**
* This will return a JS Date object with a valid date input.
* Unless this will return a false status
*/
function checkDate(input) {
// const timeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
if (input instanceof Date && !isNaN(input)) {
// will execute if a valid date
return input;
} else {
// If not a valid date
const splitter = input.indexOf('/') === -1 ? '-' : '/';
const dateArr = input.split(splitter);
if(dateArr.length === 3) {
const year = dateArr[2].length === 2 ? '20' + dateArr[2] : dateArr[2];
const NewTime = new Date(Date.UTC(year, dateArr[1]-1, dateArr[0], 0, 0, 0));
return NewTime;
} else {
return false;
}
}
}
console.log(checkDate(new Date()));
console.log(checkDate('14/5/2022'));
Expected input
checkDate('14/5/2022') and timeZone = 'GMT+1;
Expected Output
2022-05-14T00:00:00.000 french time. Not the UTC time.
Is it possible?

Apps Script is JavaScript, and JavaScript Date objects are always in UTC.
When you return a Date object from a custom function, or directly write a Date object to a spreadsheet cell from another type of function, it is automatically converted to the timezone of the spreadsheet. To set the spreadsheet timezone, choose File > Settings > Time zone.
To write a date so that it appears to use another timezone, convert the Date to a text string for display with Utilities.formatDate(), like this:
const date = new Date();
const timezone = {
spreadsheet: SpreadsheetApp.getActive().getSpreadsheetTimeZone(),
paris: 'Europe/Paris',
};
console.log(Utilities.formatDate(date, timezone.spreadsheet, 'yyyy-MM-dd HH:mm, zzzz'));
console.log(Utilities.formatDate(date, timezone.paris, 'yyyy-MM-dd HH:mm, zzzz'));

2022-05-14T00:00:00.000 is string, so add this function
function myFormat(date) {
return date.getFullYear()
+ '-'
+ ((date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1))
+ '-'
+ (date.getDate() < 10 ? '0' + date.getDate() : date.getDate())
+ 'T00:00:00.000'
}
complete script
function checkDate(input) {
// const timeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
if (input instanceof Date && !isNaN(input)) {
// will execute if a valid date
return myFormat(input);
} else {
// If not a valid date
const splitter = input.indexOf('/') === -1 ? '-' : '/';
const dateArr = input.split(splitter);
if (dateArr.length === 3) {
const year = dateArr[2].length === 2 ? '20' + dateArr[2] : dateArr[2];
const NewTime = new Date(Date.UTC(year, dateArr[1] - 1, dateArr[0], 0, 0, 0));
return myFormat(NewTime);
} else {
return false;
}
}
}
function myFormat(date) {
return date.getFullYear()
+ '-'
+ ((date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1))
+ '-'
+ (date.getDate() < 10 ? '0' + date.getDate() : date.getDate())
+ 'T00:00:00.000'
}
function test() {
console.log(checkDate('14/05/2022'))
}

Related

How to get timezone offset as ±hh:mm in javascript?

I can get the Timezone offset with the following command as:
new Date().getTimezoneOffset() -> -330 and using moment
moment().utcOffset() as 330.
However, how do I get the format as ±hh:mm?
If you prefer moment.js you can use .format for formatting date or time.
const date = new Date();
let utc = moment(date).utcOffset()
console.log(moment(date).utcOffset(utc).format("YYYY-MM-DD HH:mm:ss Z"))
//and for `+00:00` it will be :
console.log('for GMT +0000 : '+ moment(date).tz('Africa/Monrovia').format('YYYY-MM-DD HH:mm:ss Z'))
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>
Reference : Display
You won't be able to do it without a third-party library or manually converting the value with functionality.
You can do something like:
const offset = new Date().getTimezoneOffset();
let offsetHours = parseInt(Math.abs(offset/60));
let offsetMins = Math.abs(offset%60);
let formattedOffset;
if (offsetHours < 10) offSetHours = '0' + offsetHours;
if (offsetMins < 10) offsetMins = '0' + offsetMins;
if (offset < 0) {
formattedOffset = '+' + offsetHours + ':' + offsetMins;
} else if (offset > 0) {
formattedOffset = '-' + offsetHours + ':' + offsetMins;
} else if (offset === 0) {
formattedOffset = 'Z';
}
That should get you pretty close.

How to handle all missing leading zeros case in datetime strings in javascript?

function convertDate(date: any) {
if(typeof date == 'string') {
date = new Date(date).toISOString()
}
console.log('new')
console.log(date)
if (props.isUTC) {
return date.utc(true).toISOString()
}
return date.toISOString()
}
I need to write a date function that accepts any string and outputs at the end a datetime in this format: yyyy-mm-dd HH:mm
The issue is that the above function throws an error when we send something without a leading zero. Is there a way to fix it easily?
2022-08-03 03:55 //this works
2022-08-03 3:55 //this doesn't work
2022-08-3 03:55 //this doesn't work
I did try with something like this:
if (!date.isValid()) {
let day = date.getDate()
let month = date.getMonth() + 1
const year = date.getFullYear()
let hour = date.getHours()
let minute = date.getMinutes()
let second = date.getSeconds()
if (month.toString().length < 2) month = '0' + month
if (hour.toString().length < 2) hour = '0' + hour
if (day.toString().length < 2) day = '0' + day
if (minute.toString().length < 2) minute = '0' + minute
if (second.toString().length < 2) second = '0' + second
console.log('invalid')
date = new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second)
console.log(date)
}
But it didn't work.
You can split and join, padding each string with 0 until length of 2 using String.padStart()
console.log(fixDateTime("2022-08-03 3:55"));
console.log(fixDateTime("2022-8-3 3:55"));
function pad2(str, sepa) {
var arr = str.split(sepa);
arr = arr.map(item => ("" + item).padStart(2, '0'));
str = arr.join(sepa);
return str;
}
function fixDateTime(str) {
var arr = str.split(/\s+/);
var result = pad2(arr[0], '-') + " " + pad2(arr[1], ':');
return result;
}
You can format the date using the internationalization api like bellow :
function convertDate(date){
const newDate = new Date(date);
if(!newDate) return console.log('Invalid input');
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
};
// Using the internationalization api (Intl)
// syntx: Intl.DateTimeFormat(locale, options).format(value);
// locale is the langue code. eg. ('en-GB' for Great Britain English)
// option is an object with the formatting options as above.
// value is the value to be formated.
return Intl.DateTimeFormat('en-US', options).format(newDate);
}
// Note: you can use the Intl api to format numbers, currencies... you can check it out here for more info.

Generating series of dates between two given date with simplified method [duplicate]

This question already has answers here:
Javascript - get array of dates between 2 dates
(31 answers)
Closed 3 years ago.
I need to generate the series of all dates between two given dates. How ever I am not able to get desire output.
I tried using the below code. I gt an empty array.
function getDates(startDate, endDate) {
var dates = [];
var currentDate = new Date(startDate);
while (currentDate <= endDate) {
var final = currentDate.getFullYear() + '-' + (((currentDate.getMonth() + 1) < 10) ? '0' : '') + (currentDate.getMonth() + 1) + '-' + ((currentDate.getDate() < 10) ? '0' : '') + currentDate.getDate();
dates.push(final);
currentDate = currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
};
When I execute console.log(getDates("2019-10-10","2019-11-20")), I get the result as empty array. I didn't get the series of dates as a result.
As mentioned by #RobG, parsing date can yield different results hence consider using the following:
function parseDate(input) {
var parts = input.split('-');
return new Date(parts[0], parts[1] - 1, parts[2]);
}
function getDates(startDate, endDate) {
var dates = [];
var currentDate = parseDate(startDate);
endDate = parseDate(endDate);
while (currentDate <= endDate) {
var final = currentDate.getFullYear() + '-' + (((currentDate.getMonth() + 1) < 10) ? '0' : '') + (currentDate.getMonth() + 1) + '-' + ((currentDate.getDate() < 10) ? '0' : '') + currentDate.getDate();
dates.push(final);
currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
}
console.log(getDates("2019-10-10", "2019-11-20"));
Original Answer:
You could change endDate into Date type and not set currentDate as setDate is doing it for you:
function getDates(startDate, endDate) {
var dates = [];
var currentDate = new Date(startDate);
endDate = new Date(endDate);
while (currentDate <= endDate) {
var final = currentDate.getFullYear() + '-' + (((currentDate.getMonth() + 1) < 10) ? '0' : '') + (currentDate.getMonth() + 1) + '-' + ((currentDate.getDate() < 10) ? '0' : '') + currentDate.getDate();
dates.push(final);
currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
}
console.log(getDates("2019-10-10", "2019-11-20"));
You have to call new Date() on line 8.
function getDates(startDate, endDate) {
const dates = [];
let currentDate = new Date(startDate);
while (currentDate <= new Date(endDate)) {
const final = currentDate.getFullYear() + '-' + (((currentDate.getMonth() + 1) < 10) ? '0' : '') + (currentDate.getMonth() + 1) + '-' + ((currentDate.getDate() < 10) ? '0' : '') + currentDate.getDate();
dates.push(final);
currentDate = new Date(currentDate.setMonth(currentDate.getMonth()+1))
}
return dates;
};
const dates = getDates("2019-01-01", "2019-10-01");
console.log(dates);
As others have said, you're comparing a string and a Date, so things go awry.
ISO 8601 format dates can be compared as strings without being parsed to Dates. Timestamps in the format YYY-MM-DD are parsed as UTC, so you need to be careful with manipulating them. In the OP, the strings are parsed as UTC but local methods are used to format the timestamps, so they may be out by 1 day for users west of Greenwich.
One option is to use UTC methods for incrementing the date and to create strings for comparison, e.g.
// startDate, endDate in format YYYY-MM-DD
function getDates(startDate, endDate) {
let toISODate = date => date.toISOString().substr(0,10);
var dates = [];
var currentDate = new Date(startDate);
while (startDate <= endDate) {
dates.push(startDate);
currentDate.setUTCDate(currentDate.getUTCDate() + 1);
startDate = toISODate(currentDate);
}
return dates;
};
console.log(getDates('2019-09-01', '2019-10-01'));
Use a library like moment.js for date manipulation. These functions are readily available in these.
window['moment-range'].extendMoment(moment);
const start = new Date("11/30/2018"), end = new Date("09/30/2019")
const range = moment.range(moment(start), moment(end));
console.log(Array.from(range.by('day')))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/4.0.1/moment-range.js"></script>
And this question has lot of other methods as answers - from which I copied the above solution.

convert string to date and subtract X days

I need to make a function that takes a string and x number (subDays) of days as arguments and convert the string to a date and subtracts the x number of days from the date.
The input string is in format (YYYY-MM-DD) and I would like to get the same format back.
I get an Invalid Date error.
function newDate(date, subDays) {
var myDate = new Date(date);
myDate.setDate(myDate -subDays);
console.log("Date: " + myDate);
}
Here is one way you can do it
console.log( toYMD( subDays( '2016-12-11', 3) ) );
function subDays(date, days) {
var dateArray = date.split('-');
var myDate = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
return new Date(myDate.setDate(myDate.getDate() - days));
}
function toYMD(d) {
return d.getFullYear() + "-" +
padZero(d.getMonth()+1) + "-" +
padZero(d.getDate());
}
function padZero(v) {
return (v < 10) ? "0" + v : v;
}
It is recommended not to use parser of Date constructor as it can be implementation dependant, other than some widely accepted formats. So parse the string ourselves.
Make adjustments to date by getting milliseconds with getTime and adding/subtracting milliseconds.
function newDate(date, subDays) {
function padZero(v) {
return (v < 10) ? "0" + v : v;
}
var dateArray = date.split('-').map(Number);
var myDate = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
myDate = new Date(myDate.getTime() - subDays * 24 * 60 * 60 * 1000)
return myDate.getFullYear() + '-' + padZero(myDate.getMonth() + 1) + '-' + padZero(myDate.getDate());
}
console.log(newDate('2016-12-09', 8))
console.log(newDate('2016-12-09', 9))
First you have to specify what you are trying to deduct ; try this :-
function newDate(date, subDays) {
var myDate = new Date(date);
myDate.setDate(myDate.getDate() -subDays);
console.log("Date: " + myDate);
}
There is a package called datejs and you can easily use addDays(), addHours(), addMinutes() on a Date object. Here is the API doc: https://code.google.com/archive/p/datejs/wikis/APIDocumentation.wiki
function newDate(date, subDays) {
const d = Date.parse(date).addDays(-parseInt(subDays));
return `${d.getFullYear()}-${d.getMonth()}-${d.getDay()}`;
}

Make JavaScript Date function accept string or date object

I have this simple JavaScript function below that converts a JavaScript Date into a more readable format.
Right now you have to pass in a valid Date object but I would like to modify it so that it will accept a Date object or a string with a date value and return a formatted date regardless of which version is passed into it.
function formatDate(date) {
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0'+minutes : minutes;
var strTime = hours + ':' + minutes + ' ' + ampm;
return date.getMonth()+1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + strTime;
}
Usage:
var d = new Date(date_string);
var e = formatDate(d);
Converts this 2015-09-16 03:18:12 into 9/16/2015 3:18 pm
I want to be able to pass in a Date object...
var dateObject = new Date(date_string);
var e = formatDate(dateObject);
or a Date string...
var dateString = `2015-09-16 03:18:12`;
var e = formatDate(dateString);
The way to do this is to do type checking in the function via typeof.
function formatDate(date) {
if(typeof date === "string") {
// parse the date string into a Date object
}
// now date is already a Date object, or it has been parsed
var hours = date.getHours();
...
Actually parsing the Date string is outside the scope of the question.
You can check the type of variable before deciding which way to go:
function formatDate(date) {
if(typeof(date) == "string") {
var date_string = date;
date = new Date(date_string);
}
// Then just keep going!
}

Categories