Unix is passed to the argument d.
I want to use much to get only the numbers but I get an error.
error message
TypeError: Cannot read property 'match' of undefined
const date = (d) => {
const dayjs = require('dayjs');
const relativeTime = require('dayjs/plugin/relativeTime');
dayjs.extend(relativeTime);
const now = Date.now();
const day = dayjs(now - d).fromNow();
console.log(day.result.match(/[0-9]*/g));
};
You cannot read property 'match' of undefined because result is undefined. Taking a look at day.js documentation, it looks like dayjs().fromNow() returns a string output directly in your day const. Be careful as the number it returns is not just in days, the breakdown could be hours/months/years based on the total number of days as you can see if the Range table when you scroll down.
const date = (d) => {
const dayjs = require('dayjs');
const relativeTime = require('dayjs/plugin/relativeTime');
dayjs.extend(relativeTime);
const now = Date.now();
const day = dayjs(now - d).fromNow(true); //pass in true to remove the suffix 'ago'
console.log(day.split(' ')[0]);
};
Instead of a regex match, all we need to do is split the string by spaces and take the first element which is the number 2 days ago -> 2
Related
I want to compare last 30 mins data and display in UI. Datetime needs be UTC. I tried using Moment but i am getting error
Javascript - Operator '>' cannot be applied to types 'Date' and 'Moment'.
Below is my code :
let d = moment();
let d_utc = moment.utc();
var customDate = new Date();
d_utc.minutes(-30);
filteredData = filteredData.filter((category) => {
return category.uploaded_time > d_utc;
});
If you wish to compare a Date to an instance of a Moment with a Date, you need to convert them both to the same date.
You can call .toDate() to convert a moment to a Date or moment(date) to convert a Date to a Moment.
return category.uploaded_time > d_utc.toDate()
JavaScript doesn't have operator overrides, so the safest way to compare Moments is using diff:
return moment(category.uploaded_time).diff(d_utc) > 0
At the documentation in get+set section you can compare the seconds
Examplet in documentation
moment.utc().seconds(30).valueOf() === new Date().setUTCSeconds(30);
Your code should be
let d_utc = moment.utc();
let d_utc = moment.utc().minutes(-30).valueOf();
filteredData = filteredData.filter((category) => {
return category.uploaded_time.getUTCSeconds() > d_utc;
});
Also there is a query section you can check it
Here I need to compare two times and have to check whether the current time is sameOrBefore the given time.
var workingDayTime = '1900'
var currentTime = moment().format("HH:mm")
var endTime = moment(workingDayTime,"HHmm").format("HH:mm")
console.log(currentTime) // 08:21
console.log(endTime) // 19:00
Assume the value of workingDayTime is coming from API in the format of ``HHMM`. I have checked the moment docs. And used something like endTime.isSameOrAfter(currentTime).
But it is returning endTime.isSameOrAfter is not a function . I believe this is because the current time and endTime have formatted to string this is not a function anymore. Is there any way to achieve the functionality I am looking for. Please help me with your suggestion and feedback
Compare the moment objects without the string formatting:
const workingDayTime = '1900'
const currentMoment = moment()
const currentTime = currentMoment.format('HH:mm')
const endMoment = moment(workingDayTime,"HHmm")
const endTime = endMoment.format("HH:mm")
const msg = (endMoment.isSameOrAfter(currentMoment))
? 'after'
: 'before'
console.log(`${endTime} is ${msg} ${currentTime}`)
Don't format dates before you compare them
import moment from "moment";
var workingDayTime = '1900'
var currentTime = moment()
var endTime = moment(workingDayTime,"HHmm")
console.log(endTime.isSameOrAfter(currentTime)) // true
I have duration string that looks like:
1:16.352
where 1 is minutes part, 16 is seconds part and 352 is millisecond part.
I wanted to use Duration.fromISOTime but I get:
{
"reason": "unparsable",
"explanation": "the input \"1:16.352\" can't be parsed as ISO 8601"
}
Is there a clean way of parsing such duration in Luxon?
Duration.fromISOTime does not work since 1:16.352 is not an ISO 8601 time string, the hour part is missing (see ISO 8601 Times).
A workaround to build a Luxon Duration object could be the following:
const DateTime = luxon.DateTime;
const Duration = luxon.Duration;
const startOfHour = DateTime.local().startOf('hour').toMillis();
const dt = DateTime.fromFormat("1:16.352", "m:ss.SSS"). toMillis();
const dur = Duration.fromMillis(dt - startOfHour);
console.log(dur.toFormat("m 'minute' s 'second' S 'millis'"));
<script src="https://cdn.jsdelivr.net/npm/luxon#1.26.0/build/global/luxon.js"></script>
Similarly to #VincenzoC I adjusted my input string:
const Duration = luxon.Duration;
var output;
const durationInput = "1:16.352"
if (durationInput.match(/:/g) || [].length === 1) {
const semicolonLocation = durationInput.indexOf(":");
if (semicolonLocation === 1) {
output = "00:0" + durationInput;
}
if (semicolonLocation === 2) {
output = "00:" + durationInput;
}
}
console.log(Duration.fromISOTime(output));
<script src="https://cdn.jsdelivr.net/npm/luxon#1.26.0/build/global/luxon.js"></script>
As I mentioned in the comments, you can use the fromObject static method combined with simply splitting the input into minutes, seconds, and milliseconds configuration options. In your case a trivial regular expression (\d+):(\d+)\.(\d+) should do the trick, no temporary dates or normalization required.
const { Duration } = luxon;
const durationInput = "1:16.352";
const fromCustom = (input) => {
const [, minutes, seconds, milliseconds ] = input.match(/(\d+):(\d+)\.(\d+)/);
return Duration.fromObject({
minutes, seconds, milliseconds
});
};
console.log(fromCustom(durationInput));
<script src="https://cdn.jsdelivr.net/npm/luxon#1.26.0/build/global/luxon.js"></script>
I need to compare two values, as you see in my code below.
Point is that they are in different formats, and i need them to compare.
Here is my code(daysToLeave is allways number 1-3 - this value match 1-3 days):
const tomorrow = new Date();
const tmp = tomorrow.getDate() + daysToLeave;
tomorrow.setDate(tmp);
console.log("eventDate.date", eventDate?.date);
console.log("tommorrow", tomorrow);
if (eventDate?.date < tomorrow) {
console.log("success");
}
Here are my console.logs:
use moment and .diff().
//Determine the unit of difference between
const type = ["years","months","weeks","days","hours","minutes"]
moment(tomorrow).diff(eventDate?.date.toDate(), type[3])
All I am trying to do is this.
Let's say in Google Sheets, I have a page which has the following columns:
In column I3 I have the date of 11/30/19.
In column J3, I have Today's date of 4/30/20.
I want to be able to calculate the difference between these two dates and tell me how many months has it been since 11/30/19.
Currently, I think the code is working somewhat but the result I get is:
[20-05-02 01:43:18:650 MDT] 5 months, 6 days
[20-05-02 01:43:18:656 MDT] 5 months, 6 days
[20-05-02 01:43:18:660 MDT] 5 months, 6 days
But the date calculations are still wrong. For example from Jan 1st - Jan 25, 2020, it shows 5 month and 6 days.
Also the loop I have inside Filter 1, is just calculating the first available date and then it does this three times instead of going to the next record and calculate.
I have the following code so far:
function myFunction() {
}
var moment = Moment.load();
/**
* #summary gets date difference
* #param {Date} startDate
* #param {Date} endDate
* #returns {string}
*/
function getDuration(startDate, endDate) {
const start = moment(startDate);
const end = moment(endDate);
const units = ['years', 'months', 'days'];
const lastIndex = units.length - 1;
const parts = units
.map((unit,i) => {
const diff = Math.floor(end.diff(start, unit, true));
if (diff > 0 || i === lastIndex) {
end.subtract(unit, diff);
return `${diff} ${unit}`;
}
})
.filter(Boolean);
return parts.join(', ');
}
function Filter2() { // Calculate the Time
const spread = SpreadsheetApp.getActiveSpreadsheet();
const sheets = spread.getSheets();
const [ sheet_1, sheet_2 ] = sheets;
const row = sheet_1.getRange("A:M");
const arr_col = sheet_1.getRange("I3:I50");
const lastSeen_col = sheet_1.getRange("J3:J50");
const startDate = arr_col.getValue();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var headerRowNumber = 2;
var rows = sheet.getDataRange().offset(headerRowNumber, 0, sheet.getLastRow() - headerRowNumber).getValues();
var filter = rows.filter(row => row[9] !== '');
// var digest = filter[0][9];
for(var i=0;i<filter.length; i++){
var res = getDuration(startDate, lastSeen_col);
Logger.log(res);
}
}
Why Dec, 31 1969
31st of December, 1969 in GMT-7 timezone offset is January 1st, 1970 00:00:00 UTC, which is the unix epoch. Therefore it is likely to be caused by an invalid date format passed to the Moment class instance.
Problem
getRange() method call returns an instance of Range from which you have to extract value via getValue() / getValues() before being able to use it. With that in mind, let's track what's going on in your script:
var ArrRow = sheet_1.getRange("I3:I") returns an instance of Range
mydata1 is defined somewhere globally (let's assume it holds an instance of Date)
getDuration is thus called like this: getDuration( <Range>, <Date> )
startDate and endDate are respectively an instance of Range and Date
start and end hold results of invoking the moment factory that creates a wrapper around Date object.
Step 5 is most likely to be the culprit, as per Moment library docs, moment() can accept String, Number, Date instances as well as format options, but start recieves a Range instance instead.
Possible solution
First, you need to ensure you pass in correct types (this why a lot of folks prefer TypeScript - if that's not your cup of tea, at least start using JSDoc - it will save you a ton of debug time).
I don't know how big the I3:I range is, so I assumed from the context that it is a single cell containing start date. Also note that I removed the var sld = new Date(dateString) assignment since you return a human readable string from getDuration() of format Y years, M months, D days which is not a dateString that Date constructor can accept.
Additionally, I would suggest changing forEach() to map() method for cleaner and less side effect prone code. General rule of thumb is that if input and output are of the same type, you likely want to use a mapping function.
function myFunction() {
Filter2();
}
function Filter2() {
const spread = SpreadsheetApp.getActiveSpreadsheet();
const sheets = spread.getSheets();
const [ sheet_1, sheet_2 ] = sheets;
const arr_col = sheet_1.getRange("I3:I");
const startDate = arr_col.getValue();
var dateString = getDuration(startDate, mydata1);
Logger.log(dateString);
}
var moment = Moment.load();
/**
* #summary gets date difference
* #param {Date} startDate
* #param {Date} endDate
* #returns {string}
*/
function getDuration(startDate, endDate) {
const start = moment(startDate);
const end = moment(endDate);
const units = ['years', 'months', 'days'];
const lastIndex = units.length - 1;
const parts = units
.map((unit,i) => {
const diff = Math.floor(end.diff(start, unit, true));
if (diff > 5 || i === lastIndex) {
end.subtract(unit, diff);
return `${diff} ${unit}`;
}
})
.filter(Boolean);
return parts.join(', ');
}
Notes
The answer assumes you use V8 engine (if you don't - switch to it, old one will be deprecated some time in the future, and as a bonus you get to use all the juciest language features [well, most of them]).
References
Date constructor docs on MDN
Range class docs
getValue() method docs
getValues() method docs