Find the closest hour [javascript] - javascript

I have a list of these items:
hours = ['19:30', '20:10', '20:30', '21:00', '22:00']
Assuming that now it's 20:18, how can I get the '20:10' item from the list? I want to use this to find the currently running show in a TV Guide.

First we should parse it to datetime in some way:
function parseTime(str) {
var values = str.split(':');
var hour = parseInt(values[0]);
var minutes = parseInt(values[1]);
var d = new Date();
d.setHours(hour);
d.setMinutes(minutes);
return d;
}
var now = new Date();
var bestMatch = undefined;
var bestMatchDiff = undefined;
And finally:
for(var i=0; i<hours.length; i++) {
var parsedTime = parseTime(hours[i]);
var diff = Math.abs(now - parsedTime);
if (!bestMatchDiff || bestMatchDiff>diff) {
bestMatch = parsedTime;
bestMatchDiff = diff;
}
}
bestMatch would be the closest time. This is not the currently running show now. For that, you need to ignore times that are yet to come:
for(var i=0; i<hours.length; i++) {
var parsedTime = parseTime(hours[i]);
var diff = Math.abs(now - parsedTime);
if (now<parsedTime) {
continue;
}
if (!bestMatchDiff || bestMatchDiff>diff) {
bestMatch = parsedTime;
bestMatchDiff = diff;
}
}
But keep in mind this might return undefined even if your list is not empty.

var hours = ['19:30', '20:10', '20:30', '21:00', '22:00']
var diffrenceTime
var selectedShow
var d1 = new Date()
var currentHH = 20
var currentMM = 18
d1.setHours(currentHH, currentMM, 0)
hours.forEach(v => {
var d2 = new Date()
var hh = v.split(':')[0]
var mm = v.split(':')[1]
d2.setHours(hh, mm, 0)
if (diffrenceTime == undefined) {
diffrenceTime = d2 - d1
selectedShow = v
}
if (d2 - d1 < 0 && d2 - d1 >= diffrenceTime) {
diffrenceTime = d2 - d1
selectedShow = v
}
})
console.log(selectedShow)

To find the currently running show (of course more validations need to be added):
const currentShow = hours[
hours.findIndex(
(c) => new Date(`01/01/2000 ${c}`) - new Date(`01/01/2000 20:31`) >= 0
) - 1
];
To find the next show:
const nextShow = hours.find(
(c) => new Date(`01/01/2000 ${c}`) - new Date(`01/01/2000 20:31`) >= 0
);

Well, you could do something like this
var originalArray = ['19:30', '20:10', '20:30', '21:00', '22:00'];
var newArray = originalArray.map(i=>{
return i.split(":")
})
newArray.forEach((k, idx)=>{newArray[idx] = parseInt(k[0]) + parseInt(k[1])/60})
console.log(newArray);
var time = "20:18".split(':');
var t = parseInt(time[0])+ parseInt(time[1])/60;
console.log(t);
var closestTimeIndex = 0, closestDistance = Math.abs(t-newArray[closestTimeIndex]);
for(var m=1; m<newArray.length;m++){
if(Math.abs(newArray[m]-t) < closestDistance){
closestDistance = Math.abs(newArray[m]-t);
closestTimeIndex = m;
}
}
console.log("colsest time is: " + originalArray[closestTimeIndex]);

Related

Image Download error in Google Earth Engine: "Image.date: Image '1' has a 'system:time_start' property which is not a number: 2005-09-01T00:00:00"

I want to download the time series of MODIS rasters from GEE,
var batch = require('users/fitoprincipe/geetools:batch')
print("batch.help", batch.help)
var doy = function(img) {
var firstDayOfYear = ee.Number(img
.get("system:time_start"))
.divide(24*60*60*1000);
var doy = img.subtract(firstDayOfYear).add(1);
return doy
.set("system:time_start", img.get("system:time_start"));
};
var roi = Haryana
var modis_vegetation = ee.ImageCollection("MODIS/006/MOD13Q1")
.filterBounds(roi);
var startyear = 2000;
var endyear = 2005;
var startmonth = 9;
var endmonth = 9;
var startdate = ee.Date.fromYMD(startyear, startmonth, 1);
var enddate = ee.Date.fromYMD(endyear , endmonth, 30);
var years = ee.List.sequence(startyear, endyear);
var months = ee.List.sequence(startmonth,endmonth);
var ndviCollection = modis_vegetation
.filterDate(startdate, enddate)
.select("NDVI");
var monthlyNDVI = ee.ImageCollection.fromImages(
years.map(function (y) {
return months.map(function(m) {
var monthly = ndviCollection
.filter(ee.Filter.calendarRange(y, y, "year"))
.filter(ee.Filter.calendarRange(m, m, "month"))
.mean();
return monthly
.set("year", y)
.set("month", m)
.set("system:time_start", ee.Date.fromYMD(y, m, 1));}); })
.flatten());
while batch downloading the image collection it is throwing the error which is "Image.date: Image '5' has a 'system:time_start' property which is not a number: 2005-09-01T00:00:00"
var count = monthlyNDVI.size()
var all_tiles_monthlyNDVI = monthlyNDVI.map(function(image) { return image.reproject('EPSG:4326', null, 250); });
var monthlyNDVI_colList = all_tiles_monthlyNDVI.toList(all_tiles_monthlyNDVI.size());
var n = monthlyNDVI_colList.size().getInfo();
for (var i = 0; i < n; i++) {
var img = ee.Image(monthlyNDVI_colList.get(i));
var id = img.id().getInfo();
var listOfImages = all_tiles_monthlyNDVI.toList(all_tiles_monthlyNDVI.size());
var Tile = listOfImages.get(i);
var allRasters = ee.ImageCollection.fromImages([Tile]);
print("Raster no " + i, allRasters)
batch.Download.ImageCollection.toDrive(allRasters, "MODIS",
{name: 'monthlyNDVI_250_m_'+id,
scale: 250,
region: shapefile_to_use
})
}
How to convert this 'system:time_start' property to number?
Change
.set("system:time_start", ee.Date.fromYMD(y, m, 1))
to
.set("system:time_start", ee.Date.fromYMD(y, m, 1).millis())
to get the correct numerical value (milliseconds since Jan 1 1970) for a system:time_start property.

Google Apps script returning every date minus one day

I assume it has something to do with timezone, but I cannot figure out how to add a day. I would like to only display the month. The issue is at the bottom of the code:
function compull() {
var linkssheet = SpreadsheetApp.openById("1hxkrSKhoUyveyK7dLr-xPpYxhZVvlKJt3S5L6rpMS7w").getSheetByName("Links");
var comsource = SpreadsheetApp.openById("1egqeIX6Lf2As2tsT0U8yhV41fg7as3dOLnwGryU9GVs");
var adjustmentssource = comsource.getSheetByName("Adjustments").getRange("A:I").getValues().filter(function(item){ return item[0] != ""; });
var compullsource = comsource.getSheetByName("Calculator").getRange("A:Q").getValues().filter(function(item){ return item[0] != ""; });
//var length = 4;
var length = 1 + getLastRowSpecial(linkssheet.getRange("E:E").getValues());
var comlength = 1 + getLastRowSpecial(compullsource);
var adjlength = 1 + getLastRowSpecial(adjustmentssource);
for (i=2; i<length; i++) {
var writelocation = SpreadsheetApp.openByUrl(linkssheet.getRange(i,5).getValue());
var compull = writelocation.getSheetByName("Commissions");
var id = linkssheet.getRange(i,1).getDisplayValue();
var id2 = linkssheet.getRange(i,2).getDisplayValue();
var rowlength = comlength;
var columnlength = compullsource[0].length;
dataarray = [];
dataarray.push(compullsource[0].slice());
for (j=1;j<compullsource.length;j++){
if(compullsource[j][1] == id){
dataarray.push(compullsource[j].slice());
}
}
for (k=0;k<dataarray.length;k++){
dataarray[k].splice(1,2);
}
compull.getRange(4,1,dataarray.length,dataarray[0].length).clearContent();
compull.getRange(4,1,dataarray.length,dataarray[0].length).setValues(dataarray);
var rowlength = adjlength;
var columnlength = adjustmentssource[0].length;
dataarray2 = [];
dataarray2.push(adjustmentssource[0].slice());
for (j=1;j<adjustmentssource.length;j++){
if(adjustmentssource[j][1] == id2){
dataarray2.push(adjustmentssource[j].slice());
}
}
for (k=0;k<dataarray2.length;k++){
dataarray2[k].splice(0,2);
}
compull.getRange(4,17,dataarray2.length,dataarray2[0].length).clearContent();
compull.getRange(4,17,dataarray2.length,dataarray2[0].length).setValues(dataarray2);
SpreadsheetApp.flush();
//change date in adjustments in Column Q
var date = compull.getRange("Q5:Q")
var values = date.getValues();
values[0][0] = Utilities.formatDate(date, "GMT-8:00", "MM");
You should know that the spreadsheet settings and the script project have their own timezone, so if you have problems with dates one of the first things that you should check is that each of them is using the correct timezone.
This part of the code is wrong
var date = compull.getRange("Q5:Q")
var values = date.getValues();
values[0][0] = Utilities.formatDate(date, "GMT-8:00", "MM");
The problem is that the first argument of formatDate should be a Date object but date had assigned a Range object.
Resources
Working with Dates and Times

Get the minimum and maximum dates from JSON

There JSON:
[{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
As in JavaScript to get the maximum and minimum date of it?
var array = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var max = null;
var min = null;
for (var i = 0; i < array.length; i++) {
var current = array[i];
if (max === null || current.source > max.source) {
max = current;
}
if (min === null || current.source < min.source) {
min = current;
}
}
document.getElementById('maxResult').innerHTML = max.source;
document.getElementById('minResult').innerHTML = min.source;
Max: <span id="maxResult"></span><br/ >
Min: <span id="minResult"></span>
You could do something like this, provided your date format is "yyyy-MM-dd".
Convert the date string to dateKey. which always follow the ascending order as the dates proceed. 20160101(Jan 1st) is always less than 20161231(Dec 31st).
Keeping that in mind, just convert the dates to dateKey and map dateKeys to the object and just extract the max and min of the dateKeys and return the actual date.
var datesArray = [{
"source": "2016-11-02",
"sourcecount": 38
}, {
"source": "2016-11-10",
"sourcecount": 30
}, {
"source": "2016-11-31",
"sourcecount": 38
}, {
"source": "2016-01-01",
"sourcecount": 30
}];
var newObject = {};
var dates = datesArray.map(function(obj) {
var regEx = new RegExp(/-/g);
//Convert date to dateKey
var dateKey = parseInt(obj.source.replace(regEx, ""), 10)
newObject[dateKey] = obj;
return dateKey;
});
console.log("Max", newObject[Math.max(...dates)].source);
console.log("Min", newObject[Math.min(...dates)].source);
The good thing is, your date is in ISO 8601 format already. You can just simply do this,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var dateArr = data.map(function(v) {
return new Date(v.source);
});
// Sort the date
dateArr.sort(function(a, b) {
return a.getTime() - b.getTime();
// OR `return a - b`
});
// The highest date is in the very last of array
var highestDate = dateArr[dateArr.length - 1];
// The lowest is in the very first..
var lowestDate = dateArr[0];
Or you prefer to have your original object instead, then you can do,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
data.sort(function(a,b) {
var date1 = (new Date(a.source));
var date2 = (new Date(b.source));
return date1 - date2;
});
// highest date is '2016-11-03'
var highestDate = data[data.length - 1].source
// lowest date is '2016-11-01'
var lowestDate = data[0].source
Try this
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
function compare(a,b) {
if (new Date(a.source) < new Date(b.source))
return -1;
if (new Date(a.source) > new Date(b.source))
return 1;
return 0;
}
data = data.sort(compare);
var minDate = data[0].source;
var maxDate = data[data.length - 1].source;

how to calculate values of an (javascript) object with date keys

I have the following simplified (javascript) object, of which properties are dates (in string fomat):
Given a random startdate and enddate within the range of dates in the object, how to code (efficiently) the calculation - say accumulate- of the values within this range? As an example, for the following code the calculation result should be 12 (3+4+5) for the given startdate and enddate.
var startdate = '2014-01-03';
var enddate = '2014-01-05'
var obj = {};
obj['2014-01-02'] = '2';
obj['2014-01-03'] = '3';
obj['2014-01-04'] = '4';
obj['2014-01-05'] = '5';
obj['2014-01-06'] = '6';
You can just loop through the properties of the object, doing a comparison, and adding.
var startdate = '2014-01-04';
var enddate = '2014-01-05';
var arr = {};
arr['2014-01-02'] = '2';
arr['2014-01-03'] = '3';
arr['2014-01-04'] = '4';
arr['2014-01-05'] = '5';
arr['2014-01-06'] = '6';
var total = 0;
for(var p in arr) {
if(arr.hasOwnProperty(p)) {
if(new Date(p) >= new Date(startdate) && new Date(p) <= new Date(enddate)) {
total += parseInt(arr[p], 10);
}
}
}
console.log(total);
Sample http://jsbin.com/imUdewaJ/1/edit
I'm sure there is a better way to do this, but I don't know how due to having to parse the date object out for comparison.
--Edit added in the hasOwnProperty check from comments below
When doing stuff with dates, you might want to use thirdparty tools to handle browser compatibility. Momentjs is a good one for dates.
solution with momentjs:
var startdate = moment('2014-01-03');
var enddate = moment('2014-01-05');
var obj = {};
obj['2014-01-02'] = '2';
obj['2014-01-03'] = '3';
obj['2014-01-04'] = '4';
obj['2014-01-05'] = '5';
obj['2014-01-06'] = '6';
var strDate;
var total = 0;
for (strDate in obj) {
if (obj.hasOwnProperty(strDate)) {
var date = moment(strDate)
if (date.diff(startdate, 'days')>=0 && date.diff(enddate, 'days')<=0) {
total += parseInt(obj[strDate], 10);
}
}
}
console.log(total);
It's possible that some browsers won't support date1 > date2, so it might be better to also use getTime().
function getDate(date) {
return new Date(date).getTime();
}
function getTotal(start, end) {
var total = 0;
for (var k in obj) {
var current = getDate(k);
if (current >= start && current <= end) {
total += parseInt(obj[k], 10);
}
}
return total;
}
var start = getDate(startdate);
var end = getDate(enddate);
console.log(getTotal(start, end)); // 12

Validate user input dates are in given date range using javascript

I am new to php and javascript. this is what put me in to trouble
There are two dates given by administration.
var a="24/05/2013";
var b="26/05/2013";
Assume if user select check in Date as : 17/05/2013 and check out date as : 30/05/2013.
as you can see, those selected dates are in between above mentioned dates (var a and var b).
so how can i validate that scenario using JAVASCRIPT.
need a support on this.
thanks in advance
try this
function dateCheck() {
var fDate = new Date("24/05/2013");
var lDate; = new Date("26/05/2013");
fDate = Date.parse(document.getElementById("fDate").value);
lDate = Date.parse(document.getElementById("lDate").value);
if(fDate <= lDate) {
alert("true");
return true;
}
alert("false");
return false;
}
I'll do it like this:
function dateCheck() {
var a = new Date("24/05/2013");
var b = new Date("26/05/2013");
var checkinDate = Date.parse(document.getElementById("checkinDate").value);
var checkoutDate = Date.parse(document.getElementById("checkoutDate").value);
return((checkinDate >= a && checkinDate <= b) &&
(checkoutDate <= b && checkoutDate >= a) &&
(checkoutDate > checkinDate))
}
Edit: As per clarification with OP
function dateCheck() {
var a = new Date("24/05/2013");
var b = new Date("26/05/2013");
var checkinDate = Date.parse(document.getElementById("checkinDate").value);
var checkoutDate = Date.parse(document.getElementById("checkoutDate").value);
return(( a > checkinDate && a < checkoutDate) &&
(b < checkoutDate && b > checkinDate) &&
(checkoutDate > checkinDate))
}
Try this :-
var fdt= new Date("20/02/2013");
var tdt = new Date("10/05/2013");
function validateFromAndToDate(fdt,tdt){
var dt1 = dte1.value.substring(0,2);
var mon1 = dte1.value.substring(3,5);
var yr1 =dte1.value.substring(6,10);
var dt2 = dte2.value.substring(0,2);
var mon2 = dte2.value.substring(3,5);
var yr2 = dte2.value.substring(6,10);
var date1 = new Date(yr1, mon1-1, dt1);
var date2 = new Date(yr2, mon2-1, dt2);
if (date2<date1){
alert("Date period must be within the given date!");
return false
}
return true
}
It works fine.

Categories

Resources