Display a date fortnightly using javascript - javascript

This is my first time posting a question on here however I am a long term user of StackOverflow.
I am very new to Javascript and am currently trying to solve a few issues I am having on a website I am creating for my university course.
I am trying to make a little information box on the website's dashboard that simply tells you when your next rubbish bin collection day is. This is currently every 2 weeks on a Friday, the next being 1st April. I was wondering if there was a simple way for me to display the next bin collection date until it's the day of the bin collection, where the text would change to say 'bin collection today!' and after about 6pm it would change to the next collection date in a fortnight.
Sorry if this is extremely poorly worded! The website will only be used in the UK so I don't need to worry about time zones.
Any help would be very much appreciated!
Many thanks,
Emily

Below is some code to show how it might be done, hopefully there are sufficient comments.
As far as I know, some parts of the UK observe daylight saving but the following should not be affected by any change of timezone since it uses local date methods.
Any date can be used for the start of the cycle, I've chosen 10 June 2011 totally randomly. Also, any time of day can be used to change the message on the final day from "put your bins out today" to the standard "next cycle is in x days".
The algorithm is calculate the number of milliseconds to the next full fortnight from the start date by subtracting the number of milliseconds from the last full fortnight from the milliseconds per fortnight. Then the remainder is converted to full days.
To save ambiguity on the day before the cycle ends (in this case, a Thursday) the message says the cycle ends "tomorrow" rather than in 1 day, and on the day itself, up to 18:00 or 6 pm it says the cycle ends today. After that, it says the cycle ends in 14 days or less.
// Date objects are based on milliseconds (8.64e7 per day)
// Calculate milliseconds for a fortnight
var msPerFortnight = 8.64e7 * 14;
// Any date can be the start of the fortnightly cycle
// Make Friday 10 June 2011 first day of cycle,
// Cycles end on 25 March, 6 April 2016.
// Note months are zero based so June is 5
var firstDayOfCycle = new Date(2011, 5, 10);
// Time of day to stop showing "put bins out today" message on start/end day
// 18 is 6 pm
var endHour = 18;
// Get the day name for the cycle start/end
var dayName = ['Sunday','Monday','Tuesday','Wednesday','Thursday',
'Friday','Saturday'][firstDayOfCycle.getDay()];
// Convert end hour to convenient format with am/pm
var endHourNeat = (endHour % 12 || 12) + ' ' + (endHour < 12? 'am' : 'pm');
// Get a date for now
var now = new Date();
// Get milliseconds to next full fortnight by
// msPerFortnight minus milliseconds since last full fortnight
var m = msPerFortnight - ((new Date() - firstDayOfCycle) % msPerFortnight);
// Calculate time remaining full days
var daysLeft = Math.ceil(m / 8.64e7);
// Create a human friendly message
var message;
// If more then one day left, or after 18:00 on last day, show this message
if (daysLeft == 14 && now.getHours() < endHour) {
message = 'Today is ' + dayName + ', so please put your bins out before ' + endHourNeat + '!';
} else if (daysLeft > 1 ) {
message = 'Put your bins out on ' + dayName + ' in ' + daysLeft +
' day' + (daysLeft == 1?'':'s') + ' time.';
} else if (daysLeft == 1) {
message = 'Put your bins out tomorrow, on ' + dayName + '.';
}
document.write(message);
You can even add the date of the end of the cycle and add ordinal, so it might read "Put your bins out on Friday the 25th, in 3 days time". But I'll leave that up to you.

A possible solution is to use Unix epoch, because they give you your time in seconds from 1/1/1970. By using this we can find how far we are into a fortnight. I found that Math.floor(Date.parse("2016-04-01")/86400000)%14equals 8.
Then your code might be:
var days_into_fortnight=Math.floor(Date.now()/86400000)%14;
var string_to_show;
var days_to_collection;
if (days_into_fortnight==8){
string_to_show="Bin collection!";
}
else{
if(days_into_fortnight<8){
days_to_collection=8-days_into_fortnight;
}
else{
days_to_collection=22-days_into_fortnight;
}
string_to_show=days_to_collection.toString()+" day(s) to collection!";
}
Edit:spelling

Related

Moment js - days remaining - incorrect value coming back

https://jsfiddle.net/yg4bk1wh/
I am trying to create a tool that reports the days remaining -
moment(1583884740000).diff(moment(), 'days')
but this is reporting incorrectly - almost as if the month index is not taken into consideration.
-- also if the days became negative - would want to obtain the value without the polarisation - so intead of "10 days remaining" -- it reads "finished 30 days ago"
-- https://www.calendar-12.com/days_between_dates
scenario 1
Start Date - February 12th
End Date - March 10th
total days between the two dates - 27 days
remaining days from now until end day - 33 days
^ campaign has yet to start
scenario 2
Start Date -January 6
End Date - March 10th
total days between the two dates - 64 days
remaining days from now until end day - 33 days
so the campaign has been running (64-33) = 31 days [totaldays-remaining days]
as such the campaign is (31/64 * 100) % complete [48%]
In your jsfiddle, you're formatting the date wrong, which returns a wrong display date.
See snippet:
console.log(moment(1583884740000).format('MMMM d YYYY'))
console.log(moment(1583884740000).format('MMMM D YYYY'))
<script src="https://unpkg.com/moment#2.24.0/min/moment.min.js"></script>
moment(1583884740000).format('MMMM D YYYY') returns 'March 11 2020' which is the correct amount of days after today.
In your line with days remaining, you are using the current date instead of your first date. moment() will return the current date and time.
m[2] = ["days remaining", moment(1583884740000).diff(moment(), 'days')];
Put your first timestamp in and the result will be 27 days remaining, which is correct.
m[2] = ["days remaining", moment(1583884740000).diff(moment(1581465600000), 'days')];
Here's a working fork of your fiddle: https://jsfiddle.net/bd91mjs7/2/
To solve your text problem you could calculate your remaining days beforehand and change the text accordingly:
let daysLeft = moment(1583884740000).diff(moment(1581465600000);
let daysLeftLabel = daysLeft < 0 ? 'finished ago' : 'days remaining'
var m = [];
m[0] = ["moment(date1)", moment(1581465600000).format('MMMM D YYYY')];
m[1] = ["moment(date2)", moment(1583884740000).format('MMMM D YYYY')];
m[2] = [daysLeftLabel, Math.abs(daysLeft), 'days')];
Note: Math.abs() returns the absolute value, so that you don't get "-X days ago"
I'm not sure about the
"10 days remaining" -- it reads "finished 30 days ago"
part though, in my example it would read "days ago 10" instead of "days remaining -10". You may need to change the logic yourself there.
Update: as #nsevens stated, you are also using the wrong date format. Instead of d, which gets you the day of the week, you should use D which returns the day of the month (https://momentjs.com/docs/#/displaying/format/). I updated my example above.

How to make two timepickers behave like google calendar?

I try to make my timepickers behave like the ones in google calendar. What I try to achieve is that if I set the start time from 10:00 to 11:00, the 2nd should follow from 11:00 to 12:00. If I set the 2nd picker from 11 to 13, the difference is now 2 hours and if I adjust the first one, the 2nd should move +2 or -2 hours depending if its earlier or later on the day.
My current jquery code is now
var d = new Date();
var start_time = $('#calendarentryform-start_time').val();
var end_time = $('#calendarentryform-end_time').val();
var diff = ( new Date('1970-01-01 ' + end_time) - new Date('1970-01-
01 ' + start_time) ) / 1000 / 60 / 60;
var new_end_time = start_time + diff;
$('#calendarentryform-start_time').on('change',function() {
$('#calendarentryform-end_time').val(new_end_time);
}
);
It manage to find for example the hour difference on 1 hour, like the calculation is correct. But when I try to add that hour for new_end_time it just post 12:001 instead of 13:00 or whatever the time is supposed to be set to. I also want it to be able to find 1,5 hours, 2,5 hours etc.
I just dont seem to get it right.

Java script - invoice due date miscalculation

Apologies in advance for my (something less than) basic knowledge of java script.
Can someone explain in basic – but specific – terms how this script is calculating?
Here is the script:
var d = new Date(year, month, day);
var e = new Date(d.getTime() + offset * 24 * 60 * 60 * 1000);
var month_out = e.getUTCMonth();
var day_out = e.getDate();
var year_out = e.getUTCFullYear();
date_out = month_out + "-" + day_out + "-" + year_out;
year = 2013
month = 12
day = 01
offset = 15
The offset is the “payment terms” and the date is the invoice date. The output is supposed to be the invoice date plus the offset to arrive at “12-16-2013”
That is NOT what it is kicking out and I need to figure out how to fix it.
One customer is having dates show up as: 0-16-2014
I don’t know which string is wrong or how it should read in its place. This is one piece of an entire function that pulls an invoice date from an XML file, strips the time from the date and creates a new "Date_Due" using the offset. This script is the only area that is failing.
Can anyone help?
getUTCMonth() returns 0 based months - 0 is January, 1 is February, etc.
Add 1 to this value to make it more human readable.
See docs for more info.

How does weekly reminders work?

Is there an algorithm for weekly reminders ?
For example, I set a reminder for Thursday & I check the "weekly" option.
The Reminder is supposed to alert every Thursday then,but how is this done?
I thought about an idea, but I guess it's very stupid:
Get today's "day".
Get today's "date".
Get the wanted day number.
Subtract both days from each other.
using [4] get that day's date.
Increment the counter after every alert with 7.
I don't even know whether this will work or not, I'm sure there is a better way to do it, so I need your opinions before starting implementation.
PS: I use JavaScript so the functions are very limited.
It's not entirely clear what you're trying to do.
If your code needs to know whether it's Thursday, that's really easy using getDay, which gives you the day of the week:
if (new Date().getDay() === 4) {
// It's Thursday
}
The day numbers start with 0 = Sunday.
If your code needs to find the next Thursday starting on a given date:
var dt = /* ...the start date... */;
while (dt.getDay() !== 4) {
dt.setTime(dt.getTime() + 86400000)) // 86400000 = 1 day in milliseconds
}
or of course without the loop:
var dt = /* ...the start date... */;
var days = 4 - dt.getDay();
if (days < 0) {
days += 7;
}
dt.setTime(dt.getTime() + (days * 86400000));
If you have a Thursday already and you need to know the date for the next Thursday:
var nextThursday = new Date(thisThursday.getTime() + (86400000 * 7));

JavaScript time question

I am new to JavaScript but need to run a check to make sure it is daylight. I am using yahoo's weather API to pull sunrise and sunset. I'm just a little confused as to the best approach for comparing its results to the current time.
I am confused because it returns a time like sunset: '9:01 pm'. bsince there is a PM it is text. I can't think of a good way to compare it to the current time... RegExp, then convert to an integer maybe?
What would be the best approach to this, and why (sorry I'm trying to learn)?
Thanks in advance for any help.
Create a new Date() with the info from yahoo's api, then compare Date.now() with sunsetDate.getTime() and sunriseDate.getTime().
Passing today's date in mm/dd/yyyy format with the time as '9:01 pm' to the Date constructor will give you a valid date.
var today = new Date();
today = [today.getMonth()+1, today.getDate(), today.getFullYear()].join('/');
var yahooSunrise = '5:45 am';
var yahooSunset = '9:01 pm';
var sunrise = new Date(today + ' ' + yahooSunrise).getTime();
var sunset = new Date(today + ' ' + yahooSunset).getTime();
var now = Date.now();
var isDaylight = (now > sunrise && now < sunset);
This would work with something like this, but maybe you might need to change the timings to suite a particular climate:
function getNow() {
var now = new Date
if (now.getHours() < 5) { return "Could be still dark";}
else if (now.getHours() < 9) {return "Definitely day time";}
else if (now.getHours() < 17) { return "Definitely day time"; }
else {return "It gets dark now";}
}
alert(getNow());
One quick approach is to turn both the current time of day and the time you get back from yahoo into the value "minutes since the beginning of the day."
For example, if Yahoo gives you 9:01pm, use the pm to turn the time into 21:01. That is
21*60 + 1 = 1260 + 1 = 1261 minutes since the beginning of the day
Do this for both sunrise and suset. Then get the current time with
new Date()
and do the same kind of thing.
Then just do integer comparisons!
Hope that helps.
This sounds like a good candiidate for a regular expression on the data you get back from the service.
Something like (\d{1,2}):(\d{2})\s(AM|PM) will give you 3 capture groups.
1: The hour (1 or 2 digits)
2: The Minute (2 digits)
3: Either string "AM" or "PM"
You can then use these to parse out the actual time as integer hour and minute to compare to the current time.

Categories

Resources