Manipulation of Date & Time is overwhelmingly difficult. Mostly because there are so many formats, standards and handling techniques. Being a vRO programmer, you can’t run away from this date manipulation, be it for Reports creation, REST Calls, Data fetching or Interacting with other servers. Ask any programmer about their experience handling dates and time zones and they will probably share some war stories. Handling date and time fields is certainly not rocket science but can often be tedious and error-prone.
In this article, we will explore some of the key concepts that are necessary for manipulating date and time values correctly, formats that are convenient for storing DateTime values and transferring them over APIs, and more.
If you are sending and receiving data through a REST API, you will eventually need to convert the date to a string and vice versa because JSON doesn’t have a native data structure to represent DateTime.
Intrinsic Date() Class
vRO provides a Date() class to satisfy almost all the date and time hunger. It has a constructor that takes variety of inputs to start off. There are various methods and functions take allows quick shape-shifting of date and time. However, It may lack some quirky features that you may look out for. Let’s start off by taking a look at this Date class in a more comprehensive way.
It starts here. You call the constructor and you will get the current date and time. BOOM!
const currentDate = new Date();
If you don’t pass anything to the Date constructor, the date object returned contains the current date and time.
You can then format it to extract only the date part as follows:
const currentDate = new Date();
const currentDayOfMonth = currentDate.getDate();
const currentMonth = currentDate.getMonth(); // Be careful! January is 0, not 1
const currentYear = currentDate.getFullYear();
const dateString = currentDayOfMonth + "-" + (currentMonth + 1) + "-" + currentYear;
System.log(dateString)
//Output = "19-03-2022"
Caution It’s not getYear()
, but getFullYear()
If you instead want to get the current time stamp, you can create a new Date object and use the getTime() method.
const currentDate = new Date();
const timestamp = currentDate.getTime();
System.log(timestamp); // 1647678776796
Tip In JavaScript, a time stamp is the number of milliseconds that have passed since January 1, 1970, which is also known as Unix/ECMAScript Epoch format.
You can also take an input of Type Date in workflow or action and handle it in your scripts just like any other Date object.
Parsing a Date
Converting a string to a JavaScript date object is done in different ways.
The Date object’s constructor accepts a wide variety of date formats:
const date1 = new Date("Wed, 27 July 2016 13:30:00");
const date2 = new Date("Wed, 27 July 2016 07:45:00 UTC");
const date3 = new Date("27 July 2016 13:30:00 UTC+05:45");
or we can also use Date.parse(), that will return timestamp as string
var ms = Date.parse("27 July 2016 13:30:00 UTC+05:45");
System.log(ms); // 1469605500000 (timestamp)
Note that you do not need to include the day of week because JS can determine the day of the week for any date.
You can also pass in the year, month, day, hours, minutes, and seconds as separate arguments:
const date = new Date(2016, 6, 27, 13, 30, 0);
or you can even pass the Unix Epoch number directly:
const date = new Date(1647678776796);
that means to get the zeroth timestamp i.e. Jan 1st of 1970 UTC+0, pass 0 as a parameter to Date()
const date = new Date(0);
Working with ISO 8601 Format (YYYY-MM-DDTHH:mm:ss.SSSZ)
Of course, you can always use this specific ISO date format:
const date = new Date("2016-07-27T07:45:00.000Z"); // Fri Sep 02 2022 07:45:00 GMT-0000 (GMT)
Get Current Date in ISO complete format
Many a times, we need Dates in a complete ISO format [YYYY-MM-DDTHH:mm:ss.SSSZ], for making REST calls etc. We can use the toISOString()
or toJSON()
methods of the Date object to convert the local DateTime to UTC.
const dateFromUI = "12-13-2022";
const timeFromUI = "15:20";
const dateParts = dateFromUI.split("-");
const timeParts = timeFromUI.split(":");
const date = new Date(dateParts[2], dateParts[0]-1, dateParts[1], timeParts[0], timeParts[1]);
const dateISO = date.toISOString();
System.log(dateISO); //2022-12-13T15:20:00.000Z
Caution Not all variations of ISO 8601 format are supported by Date() constructor in vRO.
const date = new Date("2016-07-27T07:45:00Z"); // Invalid Date
If you are sure of the format you want to use, it is best to extract individual bits using the JavaScript functions we covered above and create a string yourself.
var currentDate = new Date();
var date = currentDate.getDate();
var month = currentDate.getMonth();
var year = currentDate.getFullYear();
We can get the date in MM/DD/YYYY format as
var monthDateYear = (month+1) + "/" + date + "/" + year;
The problem with this solution is that it can give an inconsistent length to the dates because some months and days of the month are single-digit and others double-digit. This can be problematic, for example, if you are displaying the date in a table column, because the dates don’t line up.
We can address this by using a “pad” function that adds a leading 0.
function pad(n) {
return n<10 ? '0'+n : n;
}
Now, we get the correct date in MM/DD/YYYY format using:
var mmddyyyy = pad(month + 1) + "/" + pad(date) + "/" + year;
If we want DD-MM-YYYY instead, the process is similar:
var ddmmyyyy = pad(date) + "-" + pad(month + 1) + "-" + year;
Let’s up the ante and try to print the date in “Month Date, Year” format. We will need a mapping of month indexes to names:
var monthNames = [
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
];
var dateWithFullMonthName = monthNames[month] + " " + pad(date) + ", " + year;
It is easy to determine the day of week from 0
(Sunday) to 6
(Saturday). The first day is always Sunday, so let’s add that in:
var daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
//or
//var completeDaysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
ordinalDateWithDayOfWeek = daysOfWeek[currentDate.getDay()] + ", " + ordinalDate;
By now, you might understand how to get bits of information out of dates and how to pad them. Now, let’s create an ISO format from scratch like I have done here (contains +00:00 instead of Z as per my requirement).
.gist table { margin-bottom: 0; }
<span>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
<a href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
</span>
Show hidden characters
| | function getCurrentDateInISOFormat() { |
| | //Desired Format 2016-06-14T00:00:00.000+03:00 |
| | var date = new Date(); |
| | System.log("Current Date: " + date.toGMTString()); |
| | //yy=date.getFullYear().toString().substr(2,2); |
| | var yyyy = date.getFullYear(); |
| | var mm = (date.getMonth() + 1 < 10 ? "0" : "") + (date.getMonth() + 1); |
| | var dd = (date.getDate() < 10 ? "0" : "") + date.getDate(); |
| | var HH = (date.getHours() < 10 ? "0" : "") + date.getHours(); |
| | var MM = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes(); |
| | var SS = (date.getSeconds() < 10 ? "0" : "") + date.getSeconds(); |
| | var milli = ""; |
| | if (date.getMilliseconds() < 10) |
| | milli = "00" + date.getMilliseconds(); |
| | else if (date.getMilliseconds() < 100 && date.getMilliseconds() > 10) |
| | milli = "0" + date.getMilliseconds(); |
| | else |
| | milli = date.getMilliseconds(); |
| | System.log(yyyy + "-" + mm + "-" + dd + "T" + HH + ":" + MM + ":" + SS + "." + milli + "+00:00"); |
| | return (yyyy + "-" + mm + "-" + dd + "T" + HH + ":" + MM + ":" + SS + "." + milli + "+00:00"); |
| | } |
view rawvro_getCurrentDateInISOFormat.js hosted with ❤ by GitHub
Get the number of seconds since the Unix/ECMAScript Epoch
var seconds = Math.floor(Date.now() / 1000);
Working with past and future dates
The best way to work and calculate present and future dates is by using Unix Epoch format which is conveniently the number of milliseconds after midnight January 1, 1970 till the given date expressed as a string which is IETF format. Let’s see few examples.
Important It should be noted that the maximum Date
is not of the same value as the maximum safe integer (Number.MAX_SAFE_INTEGER
is 9,007,199,254,740,991). Instead, it is defined in ECMA-262 that a maximum of ±100,000,000 (one hundred million) days relative to January 1, 1970 UTC (that is, April 20, 271821 BCE ~ September 13, 275760 CE) can be represented by the standard Date
object (equivalent to ±8,640,000,000,000,000 milliseconds).
Get current time in milliseconds
// vRO System method
System.getCurrentTime() //1647861957381
//or
//Javascript method
Date.now() //1647861957381
//or
var date = new Date(); //allows any Date to be used
System.log(date.valueOf()); //1647861957381
Lets say you want to fetch the date 4 days later relative to today, you can convert the today’s date in Unix Epoch format and add 4 x 24 x 60 x 60 x 1000 milliseconds to it and you will get a date exactly 4 days ahead with same time of the day, that because you have not changed enough milliseconds to modify the time.
var date = new Date(); //Thu Mar 21 2022 11:42:06 GMT-0000 (GMT)
System.log(date.valueOf());
var frameOfTime = date.valueOf() + (4*24*60*60*1000);
var date = new Date(frameOfTime); //Thu Mar 25 2022 11:42:06 GMT-0000 (GMT)
Now, let’s say you want to go back in time 4 hours back, You will subtract 4 x 60 x 60 x 1000 milliseconds.
var date = new Date(); //Thu Mar 21 2022 11:42:06 GMT-0000 (GMT)
var frameOfTime = date.valueOf() - (4*60*60*1000);
var date = new Date(frameOfTime); //Thu Mar 25 2022 07:42:06 GMT-0000 (GMT)
Comparing Dates
First, we need to create date objects. Fortunately, <, >, <=, and >= all work. So comparing July 19, 2014 and July 18, 2014 is as easy as:
const date1 = new Date("July 19, 2022");
const date2 = new Date("July 28, 2022");
if(date1 > date2) {
System.log("First date is more recent");
} else {
System.log("Second date is more recent");
}
Checking for equality is trickier, since two date objects representing the same date are still two different date objects and will not be equal. Comparing date strings is a bad idea because, for example, “July 20, 2022” and “20 July 2022” represent the same date but have different string representations. The snippet below illustrates the first point:
const date1 = new Date("June 10, 2003");
const date2 = new Date(date1);
const equalOrNot = date1 == date2 ? "equal" : "not equal";
System.log(equalOrNot);
This will output not equal
.
This particular case can be fixed by comparing the integer equivalents of the dates (their time stamps) as follows:
date1.getTime() == date2.getTime();
Moreover, vRO is not very good with timezones. So, the best is that we should ignore the user’s time zone and use UTC while creating the date object. There are two ways to do it:
- Create an ISO formatted date string from the user input date and use it to create a Date object. Using a valid ISO date format to create a Date object while making the intent of UTC vs local very clear.
const userEnteredDate = "12/20/1989";
const parts = userEnteredDate.split("/");
const userEnteredDateISO = parts[2] + "-" + parts[0] + "-" + parts[1];
const userEnteredDateObj = new Date(userEnteredDateISO + "T00:00:00.000Z");
const dateFromAPI = new Date("1989-12-20T00:00:00.000Z");
const result = userEnteredDateObj.getTime() == dateFromAPI.getTime(); // true
This also works if you don’t specify the time since that will default to midnight (i.e., 00:00:00Z):
const userEnteredDate = new Date("1989-12-20");
const dateFromAPI = new Date("1989-12-20T00:00:00.000Z");
const result = userEnteredDate.getTime() == dateFromAPI.getTime(); // true
Remember: If the date constructor is passed a string in correct ISO date format of YYYY-MM-DD, it assumes UTC automatically.
- JavaScript provides a neat Date.UTC() function that you can use to get the UTC time stamp of a date. We extract the components from the date and pass them to the function.
const userEnteredDate = new Date("12/20/1989");
const userEnteredDateTimeStamp = Date.UTC(userEnteredDate.getFullYear(), userEnteredDate.getMonth(), userEnteredDate.getDate(), 0, 0, 0);
const dateFromAPI = new Date("1989-12-20T00:00:00.000Z");
const result = userEnteredDateTimeStamp == dateFromAPI.getTime();
System.log(result); //true
Finding the Difference Between Two Dates
A common scenario you will come across is to find the difference between two dates.
We discuss two use cases:
FINDING THE NUMBER OF DAYS BETWEEN TWO DATES
Convert both dates to UTC time stamp, find the difference in milliseconds and find the equivalent days.
const dateFromAPI = "2016-02-10T00:00:00.000Z";
const now = new Date();
const datefromAPITimeStamp = (new Date(dateFromAPI)).getTime();
const nowTimeStamp = now.getTime();
const microSecondsDiff = Math.abs(datefromAPITimeStamp - nowTimeStamp);
// Math.round is used instead of Math.floor to account for certain DST cases
// Number of milliseconds per day =
// 24 hrs/day * 60 minutes/hour * 60 seconds/minute * 1000 ms/second
const daysDiff = Math.round(microSecondsDiff / (1000 * 60 * 60 * 24));
System.log(daysDiff); //2231
FINDING USER’S AGE FROM THEIR DATE OF BIRTH
Note: We have a non-standard format. Read the API doc to determine if this means 12 Oct or 10 Dec. Change to ISO format accordingly.
const birthDateFromAPI = "12/10/1989";
const parts = birthDateFromAPI.split("/");
const birthDateISO = parts[2] + "-" + parts[0] + "-" + parts[1];
const birthDate = new Date(birthDateISO);
const today = new Date();
var age = today.getFullYear() - birthDate.getFullYear();
if(today.getMonth() < birthDate.getMonth()) {
age--;
}
if(today.getMonth() == birthDate.getMonth() && today.getDate() < birthDate.getDate()) {
age--;
}
Find Execution time of a f(n)
You can use these logics to get more purposeful result. You can calculate the execution time of a function you just created and may optimize it.
.gist table { margin-bottom: 0; }
<span>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
<a href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
</span>
Show hidden characters
| | // To test a function and get back its return |
| | function printElapsedTime(fTest) { |
| | var StartTime = Date.now(), |
| | vReturn = fTest(), |
| | EndTime = Date.now(), |
| | difference = EndTime–StartTime |
| | |
| | System.log("Elapsed time: "+difference+" milliseconds") //5001 milliseconds |
| | return vReturn |
| | } |
| | |
| | var yourFunctionReturn = printElapsedTime(sort) |
| | |
| | function sort(){ // your function |
| | const array1 = [1, 30, 4, 21, 100000]; |
| | array1.sort(); |
| | System.log(array1); |
| | System.sleep(5000) |
| | } |
view rawvRO_function_execution_time.js hosted with ❤ by GitHub
Extras
vRO does provide various methods to represent date and time in various formats out-of-the-box. Let’s have a look on their output.
.gist table { margin-bottom: 0; }
<span>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
<a href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a>
</span>
Show hidden characters
| | var date = new Date(Date.UTC()); //Mon Jan 01 1900 00:00:00 GMT-0000 (GMT) |
| | System.log(date.toString()); //Fri Aug 23 1999 14:53:51 GMT-0000 (GMT) |
| | System.log(date.toTimeString()); //14:53:51 GMT-0000 (GMT) |
| | System.log(date.toLocaleTimeString()); //2:53:51 PM GMT |
| | System.log(date.toLocaleDateString());//January 6, 2009 |
| | System.log(date.toDateString());//Tue Jan 06 2009 |
| | System.log(date.valueOf()); //1455062400000 |
| | System.log(date.toUTCString()); // Wed, 10 Feb 2016 00:00:00 GMT |
view rawvRO_OOB_Date_functions.js hosted with ❤ by GitHub
Summary
- Date and time in JavaScript are represented with the Date object. We can’t create “only date” or “only time”:
Date
objects always carry both. - Months are counted from zero (yes, January is a zero month).
- Days of week in
getDay()
are also counted from zero (that’s Sunday). - Dates can be subtracted, giving their difference in milliseconds. That’s because a
Date
becomes the timestamp when converted to a number. - Use
Date.now()
to get the current timestamp fast.
References
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
- https://www.toptal.com/software/definitive-guide-to-datetime-manipulation
- https://www.utctime.net/
- https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range
- https://www.vroapi.com/Class/Intrinsics/1.0.0/Date
Top comments (0)