Checking if date text has milliseconds and seconds in momentjs - javascript

I am trying to parse a date from a text format to see if milliseconds and seconds were included in it.
For e.g.
let text = '2016-02-02 14:30:34.234';
const timezone = 'America/Los_Angeles';
// const hasMS = utcParse('%Y-%m-%d %H:%M:%S.')(text);
// const hasSeconds = utcParse('%Y-%m-%d %H:%M:')(text);
const hasMS = !!moment.tz(text, 'YYYY-MM-DD HH:MM:ss.', timezone);
console.log('hasMS', hasMS);
const hasSeconds = !!moment.tz(text, 'YYYY-MM-DD HH:MM:', timezone);
console.log('hasSeconds', hasSeconds);
Basically I am trying to replace the commented code. utcParse() from d3.time-format would check if the date text has milliseconds and seconds in it. I tried a couple of things for momentjs library, but it doesn't seem to work.

By using Regular expressions you can check if certain parts of the string are present.
If you call matchDateTime() with the string you get an array back with all the matched groups.
let text_min = '2016-02-02 14:30';
let text_sec = '2016-02-02 14:30:34';
let text_ms = '2016-02-02 14:30:34.234';
function matchDateTime(text) { return text.match(/(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/); }
function hasSeconds(text) { return !!matchDateTime(text)[6]; }
function hasMilliSeconds(text) { return !!matchDateTime(text)[7]; }
function testTimeString(text) {
console.log(text, "hasSeconds=", hasSeconds(text));
console.log(text, "hasMilliSeconds=", hasMilliSeconds(text));
}
testTimeString(text_min);
testTimeString(text_sec);
testTimeString(text_ms);
console.log(matchDateTime(text_ms));

Related

Time Range with an hour difference

const all = ['2021-04-26T08:00:00', '2021-04-27T10:00:00',]
const range = ["2021-04-26T00:00:00.000Z",
"2021-04-26T01:00:00.000Z",
"2021-04-26T02:00:00.000Z",
"2021-04-26T03:00:00.000Z",
"2021-04-26T04:00:00.000Z",
"2021-04-26T05:00:00.000Z",
"2021-04-26T06:00:00.000Z",
"2021-04-26T07:00:00.000Z",
"2021-04-26T08:00:00.000Z",
"2021-04-27T00:00:00.000Z",
"2021-04-27T01:00:00.000Z",
"2021-04-27T02:00:00.000Z",
"2021-04-27T03:00:00.000Z",
"2021-04-27T04:00:00.000Z",
"2021-04-27T05:00:00.000Z",
"2021-04-27T06:00:00.000Z",
"2021-04-27T07:00:00.000Z",
"2021-04-27T08:00:00.000Z",
"2021-04-27T09:00:00.000Z",
"2021-04-27T10:00:00.000Z"
]
console.log(all, range)
is it possible to loop over a list of date like (all) and get all time range from midnight with moment.js like (range)
🙏🏻 any hint
Below is an example of achieving this. It simply loops until it finds the matching end timestamp and keeps pushing the ISO strings to the ranges array.
const all = ['2021-04-26T08:00:00Z', '2021-04-27T10:00:00Z'];
const end = moment(all[1]);
let current = moment(all[0]).startOf('day');
const ranges = [];
while (!current.isSame(end)) {
ranges.push(current.toISOString());
current = current.add(1, 'hour');
}
console.log(ranges);
<script src="https://cdn.jsdelivr.net/npm/moment#2.29.1/moment.js"></script>

Combine array of dates sorted in ascending order into array of date ranges

I have one array of dates, I want to create object containing start and end by checking continue dates.
EX.
dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
]
myRequirement = [{
start: "2020-01-22T00:00:00.000Z",
end: "2020-01-23T00:00:00.000Z"
},
{
start: "2020-01-28T00:00:00.000Z",
end: "2020-02-07T00:00:00.000Z"
},
{
start: "2020-02-16T00:00:00.000Z",
end: "2020-02-20T00:00:00.000Z"
}
]
I want to do this using in node.js.
I tried this using some nested for loops.
First i am running loop on main dateArray, Then checking is it first date or not, If it is first date then storing it as first objects start date, Then in next date case checking is it next most date of previous date or not.
let gapArray = [];
let startEndObj = {};
let tempStartDate;
let tempEndDate;
let tempNextDate;
await asyncForEach(finalAvailablityDatesArrayOFi.availeblityDatesArray, async (availeblityDatesArrayOFi) => {
console.log("availeblityDatesArrayOFi", availeblityDatesArrayOFi);
if (!tempStartDate) {
console.log("In if");
startEndObj.startDate = availeblityDatesArrayOFi;
tempStartDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
console.log("startEndObj", startEndObj);
}
else if (tempStartDate) {
console.log("in else");
if (new Date(availeblityDatesArrayOFi).getTime() == new Date(tempNextDate).getTime()) {
console.log("Do nothing!");
tempStartDate = availeblityDatesArrayOFi;
tempEndDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
}
else {
startEndObj.endDate = new Date(tempEndDate);
gapArray.push(startEndObj);
tempStartDate = '';
tempEndDate = '';
startEndObj = {};
}
}
});
Thank you!
Looks like a job for Array.prototype.reduce().
Note: hereafter assumption is made that few prerequisites are met:
source array items are valid ISO-formatted date strings or others, parseable by new Date() constructor, otherwise should be brought to one of supported format
source array items are sorted in ascending order, otherwise Array.prototype.sort() method must be applied in advance
array items do not include time of the day part (or this part is exactly the same for all items), otherwise consecutive date records may happen to have difference greater than 864e5 milliseconds (1 day) and more complex comparison is required
You may walk through your array and compare current items with previous/following, once you have a gap greater than 1 day you push new range into resulting array or modify end date for the last one:
const src = ["2020-01-22T00:00:00.000Z","2020-01-23T00:00:00.000Z","2020-01-28T00:00:00.000Z","2020-01-29T00:00:00.000Z","2020-01-30T00:00:00.000Z","2020-01-31T00:00:00.000Z","2020-02-01T00:00:00.000Z","2020-02-02T00:00:00.000Z","2020-02-03T00:00:00.000Z","2020-02-04T00:00:00.000Z","2020-02-05T00:00:00.000Z","2020-02-06T00:00:00.000Z","2020-02-07T00:00:00.000Z","2020-02-16T00:00:00.000Z","2020-02-17T00:00:00.000Z","2020-02-18T00:00:00.000Z","2020-02-19T00:00:00.000Z","2020-02-20T00:00:00.000Z"],
ranges = src.reduce((res,date,idx,self) => {
const rangeStart = !idx || new Date(date) - new Date(self[idx-1]) > 864e5,
rangeEnd = idx == self.length-1 || new Date(self[idx+1]) - new Date(date) > 864e5
if(rangeStart) res.push({startdate:date,enddate:date})
else if(rangeEnd) res[res.length-1]['enddate'] = date
return res
}, [])
console.log(ranges)
.as-console-wrapper {min-height:100%}
You need to be careful with this type of processing to determine all the business rules exactly. If the time component is not to be considered, then it should be removed, otherwise when comparing say 2020-01-01T00:00:00 to 2020-01-02T012:00:00 you will get a difference greater than 1 day but might not want it to be treated as the start of a new range.
For that reason, the "days difference" logic should be in a separate function, which also makes it easier to change date libraries if you're using one. The days difference is also signed, so make sure they are passed in the right order.
Otherwise, the following is pretty much the same as Yevgen's answer but a little more efficient I think as it only creates two Dates on each iteration instead of four.
let dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
];
// Simple difference in days function
function daysDiff(d0, d1) {
return Math.round((d1 - d0) / 8.64e7);
}
let ranges = dateArray.reduce((acc, curr, i, arr) => {
// If first date, initialise first object
if (!acc.length) {
acc.push({start: curr, end: curr});
} else {
let d0 = new Date(curr);
let d1 = new Date(arr[i-1]);
// If difference greater than 1 day, end previous range
// and start a new range
if (daysDiff(d1, d0) > 1) {
acc[acc.length - 1].end = arr[i-1];
acc.push({start: curr, end: curr});
}
}
return acc;
}, []);
console.log(ranges);

How to revert toLocaleString

I need to convert a formatted number to JS default number format.
This is my code:
String.prototype.toJsFloatFormat = function() {
debugger;
var newVal = this;
return newVal;
}
//Example of use
var input = 10000.22; //default js format
var formatted = input.toLocaleString("es"); // result is: 10.000,22
var unformatted = formatted.toJsFloatFormat(); //expected result = 10000.22;
The problem is when I need to get the formatted number (10.000,22) and I make operations with this formatted number (parseFloat(10.000,22) + 1000) I have bad results ( parseFloat(10.000,22) + 1000 = 1010)
thanks in advance.
It's not easy. There's a reason why most of the comments have said "Don't try -
do your calculations on the number itself, not the formatted value".
You need to work out what the decimal and thousand separator characters are. For that, you will need to know which locale the number was converted into.
(1234.5).toLocaleString("es").match(/(\D+)/g);
// -> [".", ","]
Once you have that, you can replace characters in the formatted string.
function unformatString(string, locale) {
var parts = (1234.5).toLocaleString(locale).match(/(\D+)/g);
var unformatted = string;
unformatted = unformatted.split(parts[0]).join("");
unformatted = unformatted.split(parts[1]).join(".");
return parseFloat(unformatted);
}
There is no way of working out the locale - you have to know it and pass it to the function.
no need to reinvent the wheel -
https://github.com/globalizejs/globalize#readme
var input = 10000.22;
Globalize.parseFloat(input );
I did it this way(in my case it was the 'ru' local format, so I did replace the 'space' symbol):
var myNumber = 1000000;
var formated = myNumber.toLocaleString('ru');
var unformated = parseInt(formated.replace(/\s/g, ''));
your case:
var formated = myNumber.toLocaleString('en');
var unformated = parseInt(formated.replace(/,/g, ''));
I did this, that's fine for me
function localeStringToFloat(locale){
if(!locale) return locale
let test=1000
test=test.toLocaleString(undefined,{minimumFractionDigits: 2,maximumFractionDigits: 2});
let separator=test[1]
let decimalSeparator=test[5]
return parseFloat(locale.replaceAll(separator,'').replace(decimalSeparator,'.'))
}
My functions for format and unFormat currency numbers to 'en-US'. I hope helps
function myFormatPrice(num,digits){
return num.toLocaleString('en-US', {maximumFractionDigits:digits});
}
function myUnFormatPrice(formated){
return parseFloat( formated.replaceAll(',','') );
}

Compare dates as strings in typescript

I am trying to compare two dates as strings in typescript. The input I have is as below :-
startWindow = '05/2014'
endWindow = '05/2018'
I need to write a function to check if the start Window is greater than the end Window.
Both the inputs are of string type.
Thanks
You can convert it to a date and then compare them:
function convertDate(d)
{
var parts = d.split('/');
return new Date(parts[1], parts[0]);
}
var start = convertDate('05/2014');
var end = convertDate('05/2018');
alert(start < end);

How to test different format of dates in javascript / jquery?

I am developing a application. In this application have a input field. where the user can input the dates by different formats like
ddmmyy, ddmmyyyy, dd-mm-yy, mm-dd-yy
And I need to verify the date whether that valid or not. I can able to validate this way:
YYYY-MM-DD using:
var myDate = new Date("1987-08-06") // it returns me the date while this valid.
But I can't able to validate with other formats. how can i validate that?
example:
var myDate = new Date("08-06-1987")..etc?
I developed my app using jQuery. I am looking some solution without using a plug-in. since i used no.of plugins already.
thanks in advance!
I would do it with regular expressions. You could define a regexp pattern for each of your formats. Then you can test if the String from the input field matches any of the pattern.
Somthing like this:
var regExpDDMMYY = /[0-9]{2}[0-1][0-9][0-9]{2}/g;
var regExpddmmyyyy = ...;
...
...
if (regExpDDMMYY.test(yourInputStringFromDateField)) {
// handleDateAs DDMMYY
} else if (regExpddmmyyyy .test(yourInputStringFromDateField)) {
...
} else {
throw new YourException();
}
You can find an example here:
http://www.w3schools.com/js/js_regexp.asp
Unfortunately, there's no "parseExact" in native JS, that would also be crossbrowser. So you either need to use Date.js library or write some converter.
For this task i'd recommend you to use "Chain of responsibility" pattern
function DateTimeParser() {
this.parse = function (input) {
for (var key in Parsers) {
var result = Parsers[key].parse(input);
if (result !== null)
return result;
}
return null;
};
this.parseExact = function (input, format) {
var parser = Parsers[format];
return parser ? parser.parse(input) : null;
};
var ConcreteDateTimeParser = function (expression, parser) {
this.parse = function (input) {
if (!input.match(expression))
return null;
var result = parser(input);
return isNaN(result.getDate()) ? null : result;
};
};
var Parsers = {
"dd-mm-yyyy": new ConcreteDateTimeParser(/\d{2}\-\d{2}\-\d{4}/, function (input) {
var dd = parseInt(input.slice(0, 2)),
mm = parseInt(input.slice(3, 5)),
yyyy = parseInt(input.slice(-4));
return new Date(yyyy, mm, dd);
}),
"ddmmyyyy": new ConcreteDateTimeParser(/\d{8}/, function (input) {
var dd = parseInt(input.slice(0, 2)),
mm = parseInt(input.slice(2, 4)),
yyyy = parseInt(input.slice(-4));
return new Date(yyyy, mm, dd);
})
};
};
var instance = new DateTimeParser();
instance.parse('22122012');
instance.parseExact('22122012', 'ddmmyyyy');
instance.parseExact('22122012', 'dd-mm-yyyy'); // null
From this you can extend your Parsers lib with additional parsers. You also can use different sets of parsers by passing them into DateTimeParser as a constructor argument. My code is pretty trivial, for i didn't want to write it mega-deep, just wanted to show the way =)

Categories