Convert HH:MM:SS string to moment - javascript

I am using full calendar and I am trying to see if an event created is overlapping with the lunch breaks which I have defined as part of business hours. This is my code
function isCalendarEventOverlappingBusinessHour(event)
{
var evts = businessHoursArr;
for (i in evts)
{
var start_moment=moment(evts[i].start, 'MMM DD').format();
var end_moment=moment(evts[i].end);
if (event.start.isBefore(end_moment) && event.end.isAfter(start_moment))
{
return true;
}
}
return false;
}
I am not able to compare the event start and business hour start since in business hours, the time is defined in string format as 08:00:00. I want to convert it into a moment so that I can compare the times. Can anyone suggest a method?
My event is in the following format:
events.push({
id: guid(),
title: eventTitle,
start: moment(date),
end: moment(date).add(defaultTimedEventDuration,'hours'),
stick: true,
});
And my businesshoursarr looks like
{
dow:[1,2,3,4,5]
start:08:00:00
end:12:00:00
},
{
dow:[1,2,3,4,5]
start:13:00:00
end:17:00:00
}

I'd suggest moment(value, 'HH:mm:ss').valueOf() which will return an integer and you could just compare numbers at that point.
It'd also help if you provided an example of what businessHoursArr and event look like.
Update: Taking your code and making a few modifications, this should give you the general idea.
function isCalendarEventOverlappingBusinessHour(event) {
var evts = businessHoursArr;
var overlapping = false;
var dayFormat = 'YYYYMMDD';
var secFormat = dayFormat + 'HH:mm:ss';
var eventStartDate = event.start.format(dayFormat);
var eventEndDate = event.end.format(dayFormat);
for (i in evts) {
var start_moment = moment(eventStartDate + evts[i].start, secFormat);
var end_moment = moment(eventEndDate + evts[i].end, secFormat);
if (event.start.isBefore(end_moment) && event.end.isAfter(start_moment)) {
overlapping = true;
break;
}
}
return overlapping;
}

Related

Compare Google sheet dates to Google Calendar Event date

Matching dates from Sheet and Google Calendar is always false, how can I format the two dates to compare?
I've attemped to format the dates even if they look exactly the same it comes back false.
var Sheet_StartDate = Spreadsheet.getActiveSheet().getRange(1,1).getValue();
var calendar = CalendarApp.getCalendarById('####');
var event = calendar.getEventById(eventId);
var calendar_StartTime;
try {
// Get all day event
calendar_StartTime = event.getAllDayStartDate();
}
catch (e) {
//Multi-day event
calendar_StartTime = event.getStartTime();
}
if (calendar_StartTime === Sheet_StartDate )
{
//This comes back false
}
Try this:
function compareDates() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var dt=new Date(sh.getRange(1,1).getValue());
var Sheet_StartDate_value=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();//This removes the time portion
var calendar = CalendarApp.getCalendarById('####');
var event = calendar.getEventById(eventId);
dt=new Date(event.getAllDayStartDate());
var calendar_StartTime_value=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
if(calendar_StartTime_value == Sheet_StartDate_value ) {
//This will come back true if in fact they are the same date
}
}
You can also use Date().getTime()

Fullcalendar - Need event to not be more than a day - using selectAllow but issue with allDay

I'm using Fullcalendar and need events to not be more than a day.
I've got it working for when you pick an hour range but it never works for allDay events, as the from and to dates are different. Here is my selectAllow function. I'm aware it's not elegant, my Javascript is limited!
function(selectInfo) {
var ambig = selectInfo.start._ambigTime;
var from_date = selectInfo.start._d;
from_date = String(from_date).substr(0, 10);
var to_date = selectInfo.end._d;
to_date = String(to_date).substr(0, 10);
if (from_date != to_date)
{
return false;
}
else
{
return true;
}
var duration = moment.duration(selectInfo.end.diff(selectInfo.start));
console.log(duration.asHours());
}
As you can see from the code, I've gone down the route of having different checks based on ambigTime (I assume this is whether it's allDay or not?) and using the duration but the duration doesn't work when it's all day.
Any help much appreciated.
Actually you can solve this much more neatly and simply by using selectConstraint. This limits the user's selection to a certain window of time. By specifying it as per the following example, it effectively limits an individual selection to the day where the selection began:
selectConstraint: {
start: '00:00',
end: '24:00',
},
Demo: http://jsfiddle.net/9qv5xz18/
Thanks to ADyson, I've fixed it. I think I can neaten up the code but the below now works.
function(selectInfo) {
console.log(selectInfo);
var ambig = selectInfo.start._ambigTime;
var from_date = selectInfo.start._d;
var from_dat = selectInfo.start;
var to_dat = selectInfo.end;
console.log(to_dat.diff(from_dat))
from_date = String(from_date).substr(0, 10);
var to_date = selectInfo.end._d;
to_date = String(to_date).substr(0, 10);
if (!ambig)
{
if (from_date != to_date) {
return false;
} else {
return true;
}
}
else
{
return to_dat.diff(from_dat) == 86400000;
}
var duration = moment.duration(selectInfo.end.diff(selectInfo.start));
console.log(duration.asHours());
}

Get a combined Date from ui.bootstrap date and time pickers

I'm trying to combine the Datepicker and Timepicker directives to get the date from the first and the time from the second in a combined Date object. I came across some examples that are not using these directives like this one Combining Date and Time input strings as a Date object. However when I try to apply something similar to my case it's not working. Console returns "TypeError: $scope.dt.split is not a function". Above is the function I try to use which is called by $watch.
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
var dateParts = $scope.dt.split('-');
var timeParts = $scope.mytime.split(':');
if (dateParts && timeParts) {
dateParts[1] -= 1;
$scope.fullDate = new Date(Date.UTC.apply(undefined, dateParts.concat(timeParts))).toISOString();
}
}
}
Here is a plunker showing the problem. http://plnkr.co/edit/tnbE3LWQTTzLhLWXLCQB?p=preview
I would prefer a solution based on my Plunker as I don't want to install other components like DateTimePicker.
Date format has been changed, so exception is being thrown, Try this
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
var date = $scope.dt.toString();
var time = $scope.mytime.toString();
var dateParts = date.split(' ');
var timeParts = time.split(' ');
if (dateParts && timeParts) {
dateParts[4] = timeParts[4]
$scope.fullDate = new Date(dateParts.join(' ')).toISOString();
}
}
}
your tryCombineDateTime function sould be like this:
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
$scope.fullDate =new Date($scope.dt.getFullYear(), $scope.dt.getMonth(), $scope.dt.getDate(),$scope.mytime.getHours(),$scope.mytime.getMinutes()).toISOString();
}
}
this a working demo forked from your plunker

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 =)

Google Apps Script: How to fix "Truncating output" error when processing text from a cell as imput?

I have a Google Apps Script function which I want to use to do this: extract some data (a date) from a raw text in a spreadsheet cell. When I use a javascript IDE, the code works fine. But when I try it on GAS, it doesn't work.
This is the code:
function findDate (text){
text1 = text.split(".Date");
Logger.log("text1", text1);
//console.log("text1= ", text1);
date = 'no date informed';
for (var i=0; i<text1.length; i++) {
text2 = text1[i].split(" ");
Logger.log("text2", text2);
// console.log("text2= ", text2);
// console.log("text2[1]= ", text2[1]);
if (text2[1] === 'common:'){
date = text2[2];
Logger.log("text2[2]", text2[2]);
// console.log("text2[2]= ", text2[2]);
}
}
return date;
}
The string which is in the spreadsheet cell is not exactly this, it's writen in another language, but it's similar to this (broken text, but without the space between lines):
special term: 19 years, 6 months and 0 days.
commom term: 8 years, 8 months and 0 days.
Date special: 23/11/1998
Date common: 09/11/2012
When I get the logs, I got the message Logging output too large. Truncating output. and this text:
[text1, [[special term: 19 years, 6 months and 0 days.
commom term: 8 years, 8 months and 0 days.
Date special: 23/11/1998
Date commom: 09/11/2012]]]
THANKS in advance for any help!
You can add a sheet to your spreadsheet called Code and add a range to it for "Debug Watch" named DebugWatchWindow where you can add watches of much longer length, up to 50,000 characters. Clear the debug "window" when you start your script, and add watches wherever you want in your code.
The My Executions window is more handy, but this method is good for long log text:
Notes:
Change the reference to your code sheet and these Debug functions as necessary for your app.
DebugWatchWindow is where "fred" is. It's the top left cell of the "Debug Window" data.
don't put anything of importance below that. It will get trashed.
debug.gs
function getWatchWindow() {
if(!this.WatchWindow)
this.WatchWindow = App.Sheets.codeSheet.getRange('DebugWatchWindow').offset(0, 0, 20, 2); // fixed size
return this.WatchWindow;
}
function clearWatch() {
this.getWatchWindow().offset(0,0, App.Sheets.codeSheet.getLastRow(), 2).clearContent();
}
function addWatch(expression, value) {
var rows = App.Sheets.getLastUsedSize(this.getWatchWindow()).rows;
this.getWatchWindow().offset(rows, 0, 1, 1).setValue(expression);
this.getWatchWindow().offset(rows, 1, 1, 1).setValue(value);
}
sheets.gs
function getLastUsedSize(range) {
var values = range.getValues();
return values
.reduce(function(size, rowValues, index, values) {
var lastUsedColumn = rowValues
.map(function(cellValue, index) {
if(cellValue != '')
return index;
else
return -1;
})
.reduce(function(acc,curr) {
acc = Math.max(acc,curr);
return acc;
}, -1);
if(lastUsedColumn > -1) {
size.rows = index + 1;
size.columns = Math.max(size.columns, lastUsedColumn + 1);
}
return size;
}, {columns: 0, rows: 0});
}
tests.gs
function testScratch() {
console.log('testScratch');
App.Debug.clearWatch();
App.Debug.addWatch('fred', 14);
App.Debug.addWatch('jimmard', App.Dates.now());
sdfsdd();
}
Logger has a limited size of what it can display in the popup window and that's why it truncates the results you see.
If you remove the first occurrence in your code, which shows the initial array data, you will get the entire result. Displaying the entire array apparently exceeds the length limit.
Without this change:
using the data as above and the code as below
function myFunction() {
var text = SpreadsheetApp.getActive().getRange("A1").getValue();
Logger.log('text = '+text);
Logger.log('function result = '+findDate(text));
}
function findDate (text){
var text1 = text.split("\n"+"Date");
Logger.log("text1 = "+ text1);
var date = 'no date informed';
for (var i=0; i<text1.length; i++) {
var text2 = text1[i].split(" ");
Logger.log("text2 = "+text2);
if (text2[1] === 'common:'){
date = text2[2];
Logger.log("text2[2] = "+ text2[2]);
}
}
return date;
}
I get the following result :

Categories