Luxon - set milliseconds for toISO() - milliseconds

I'm using the following to get the end of day for a date coming from a date picker:
var date = DateTime.fromISO('2018-05-05').endOf('day');
What I want to end up with is
"2018-05-05T23:59:59+02:00"
however, I cannot get rid of the milliseconds:
console.log(date.toISO({suppressMilliseconds: true}));
// => outputs "2018-05-05T23:59:59.999+02:00"
Is there a more elegant way to do this besides simply setting the millisecond to 0:
date.c.millisecond = 0;
console.log(date.toISO({suppressMilliseconds: true}));
// => outputs "2018-05-05T23:59:59+02:00"

Right, suppressMilliseconds only applies if they're 0. (See here).
But there's a much easier way to round down the second:
DateTime.fromISO('2018-05-05')
.endOf('day')
.startOf('second')
.toISO({ suppressMilliseconds: true })
You should never mutate the Luxon object like in your workaround.

const { DateTime } = require("luxon");
let time = DateTime.now().set({milliseconds: 0});
time = time.toISO({suppressMilliseconds: true});
console.log(time);
It should help and solve the problem.

The way I did :
DateTime.now().toISO().replace(/\.\d{0,3}/, "");
Using RegExp to remove the "." and millis
I was having
2021-02-22T18:03:29.519Z
With the replace RegExp
2021-02-22T18:05:44Z

Related

How can I save part of a string in an alias using Cypress?

I'm trying to save just a number from a string I get from a paragraph but when I try to asign an alias to it and then check the value it returns undefined. I've tried a few solutions I found but none of those seem to work for me. These are two ways I tried (I tried another one similar to the second one but using split, had same result). The console.log inside of the 'then' doesn't show in the console, and when I try the alias after the code is when I get undefined.
cy.get('p')
.eq(1)
.should('have.text', '/[0-9]+/g')
.as('solNumber')
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number);
})
.as('solNumber')
Please convert with + operator and return the numeric value if you want numeric type to be stored.
cy.get('p').eq(1)
.invoke('text')
.then(fullText => {
const number = fullText.match(/[0-9]+/);
return +number // text to numeric
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', 42) // numeric type
});
Running your 2nd code on this,
<p>21</p>
<p>42</p>
gives the correct outcome
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number); // logs 42
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', '42') // passes
So, you need to inspect the DOM, it looks like it's not what you expect.
The first attempt you were passing a jquery element to the .should() and although some chainers change the subject yours did not so it saved the jquery element as solNumber.
The second attempt invokes the .text() which was passed to the .then() it logs the number correctly. However, you did not return anything at the end of the .then() block, therefore, solNumber should hold the entire paragraph.
This should help you out to extract the specific number and save it as an alias.
cy.get('p')
.invoke('text')
.invoke('trim')
.then(paragraph => {
const matcher = /some/
expect(paragraph).to.match(matcher) // check number is there
const indexOfText = paragraph.match(matcher) // get index of match text
return paragraph.substring(indexOfText.index, indexOfText.index + indexOfText[0].length) // return substring
})
.as('savedText')
cy.get('#savedText')
.then(cy.log) // will print out the number you seek

How to select efficiently from a long list of options in react-select

My use case is to allow the user to select a ticker from a long list of about 8000 companies. I fetch all the companies when the component mounts, so I don't really need the async feature of react-select. The problem really is displaying and scrolling through the 8000 items (as described in several open issues like this one).
My thought is why display 8000 entries when the user can't do anything meaningful with such a big list anyway. Instead why not show a maximum of 5 matches. As the user types more, the matches keep getting better. Specifically:
When the input is blank, show no options
When the input is a single character, there will still be hundreds of matches, but show only the first 5
As the user keeps on typing, the number of matches will reduce, but still limited to 5. However they will be more relavant.
I am not seeing this solution mentioned anywhere, so was wondering if it makes sense. Also wanted to find out what's the best way to implement it with react-select. I have tried the following two approaches - can you think of a better way:
Approach 1: Use Async React Select
Although I don't need async fetching, I can use this feature to filter down the options. It seems to work very well:
const filterCompanies = (value: string) => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
let count = 0;
return inputLength === 0
? []
: companies.filter(company => {
const keep =
count < 5 &&
(company.ticker.toLowerCase().indexOf(inputValue) >= 0 ||
company.name.toLowerCase().indexOf(inputValue) >= 0);
if (keep) {
count += 1;
}
return keep;
});
};
const promiseOptions = (inputValue: string) =>
Promise.resolve(filterCompanies(inputValue));
return (
<AsyncSelect<Company>
loadOptions={promiseOptions}
value={selectedCompany}
getOptionLabel={option => `${option.ticker} - ${option.name}`}
getOptionValue={option => option.ticker}
isClearable={true}
isSearchable={true}
onChange={handleChange}
/>
);
Approach 2: Use filterOption
Here I am using the filterOption to directly filter down the list. However it does not work very well - the filterOption function is very myopic - it gets only one candidate option at a time and needs to decide if that matches or not. Using this approach I cannot tell whether I have crossed the limit of showing 5 options or not. Net result: with blank input I am showing all 8000 options, as user starts typing, the number of options is reduced but still pretty large - so the sluggishness is still there. I would have thought that filterOption would be the more direct approach for my use case but it turns out that it is not as good as the async approach. Am I missing something?
const filterOption = (candidate: Option, input: string) => {
const { ticker, name } = candidate.data;
const inputVal = input.toLowerCase();
return (
ticker.toLowerCase().indexOf(inputVal) >= 0 ||
name.toLowerCase().indexOf(inputVal) >= 0
);
};
return (
<ReactSelect
options={companies}
value={selectedCompany}
filterOption={filterOption}
getOptionLabel={option => `${option.ticker} - ${option.name}`}
getOptionValue={option => option.ticker}
isClearable={true}
isSearchable={true}
onChange={handleChange}
/>
);
you can try using react-window to replace the menulist component
ref : https://github.com/JedWatson/react-select/issues/3128#issuecomment-431397942

Express Validatior - How Do I Break The Validation Chain?

I have a date field that I want to ensure is in a valid format and if so is the user over 18. The format is YYYY-MM-DD.
Here is one of my validators - the one that is failing:
body('birthday', 'Date format should be: YYYY-MM-DD')
.isRFC3339()
.custom(date => {
const over18 = moment().diff(date, 'years') >= 18;
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),
Currently what happens is if the date is not a RFC3339 date the validation chain continues. This is problematic because moment produces an error if I pass an ill formatted date.
How do I break the chain after the call to .isRFC3339() so that if the date is invalid the custom validator will not run? I couldn't find anything in the docs
You can use momentjs strict mode together with String + Format parsing using moment.ISO_8601 (or moment.HTML5_FMT.DATE) special formats.
Your code could be like the following:
body('birthday', 'Date format should be: YYYY-MM-DD')
// .isRFC3339() // no more needed
.custom(date => {
const mDate = moment(date, moment.ISO_8601, true);
const over18 = moment().diff(mDate, 'years') >= 18;
if(!mDate.isValid()) {
return Promise.reject('Date is not YYYY-MM-DD');
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),

Set several initial dates in inline datetimepicker tempusdominus

I'm trying to set up the datetimepicker on
https://tempusdominus.github.io/bootstrap-3/
and configure it to be used inline. It is initialized with:
$('#datetimepicker5').datetimepicker({
inline: true,
allowMultidate: true,
multidateSeparator: ';',
locale: 'nb',
format: 'L',
useCurrent: false,
});
It works, but I cannot find out how to initialize several dates.
As you can see I use it with allowMultidate.
So, how can I initialize the datetimepicker with several dates pre-set?
I met the same problem and I can't find any answers here. So I tried to resolve it with a little revise to "tempusdominus-bootstrap-4.js".
I hope this will help you and make some reference for anyone who met the same problem.
At first adding a method multiDate for Object DateTimePicker.
var DateTimePicker = function () {
…
DateTimePicker.prototype.multiDate = function multiDate(params) {
var date = params[0];
var index = params[1];
this.date(date, index);
};
…
}
The next, invoke your method at your page.
Suppose your initial data is like this:
var values = ['2019-02-06','2019-03-06','2019-05-08','2019-07-02'];
So you can initialize these in your multidatepicker.
var initializeMultidate = function(){
for(var i=0; i<values.length; i++){
var date = moment(values[i], 'YYYY-MM-DD');
$("#datetimepicker1").datetimepicker("multiDate", [date, i]);
}
};
=================================================
That's all.
The only solution I found was to do a search for the dates and using JQuery to click them, it is not elegant but it worked for me.
var fechas = ['01/10/2020', '02/10/2020', '03/10/2020'];
for (let index = 0; index < fechas.length; index++) {
$("[data-day='"+fechas[index]+"']").click();
}
Unfortunately, what you are asking cannot be done using tempusdominus. I struggled with the same issue and in the end switched over to jQueryUI MultiDatesPicker, which allows for much more control.
http://dubrox.github.io/Multiple-Dates-Picker-for-jQuery-UI/

Sorting dates with moment.js does not work when date is a link

I'm using DataTables 1.10.5. When I'm trying to sort on dates using the recommended moment.js (as per http://datatables.net/blog/2014-12-18), thinks work fine:
http://jsfiddle.net/9gohzd9t/1/
However, when I add a link (a href) to that date, it sorts on the link instead of the date:
http://jsfiddle.net/dnsL2oc4/1/
Any idea on how to properly fix this without too much hacking around?
The problem lies in the unshift method of datetime-moment.js. Moment tries to convert 12-01-2001 to a valid date in the given "DD-MM-YYYY"-Format, which it can't obviously. So you have to strip the html away from the date, probably with a function like this:
function strip(html) {
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
And then strip the string in the unshift method (Replace datetime-moment.js with the code below):
$.fn.dataTable.moment = function (format, locale) {
var types = $.fn.dataTable.ext.type;
// Add type detection
types.detect.unshift(function (d) {
return moment(strip(d), format, locale, true).isValid() ?
'moment-' + format :
null;
});
// Add sorting method - use an integer for the sorting
types.order['moment-' + format + '-pre'] = function (d) {
return moment(strip(d), format, locale, true).unix();
};
};