I use the following javascript to show a countdown timer for shipping that day
var timerRunning = setInterval(
function countDown() {
var target = 14; // This is the cut-off point
var now = new Date();
//Put this in a variable for convenience
var weekday = now.getDay();
var despatchday = 'TODAY!';
if (weekday == 0) { //Sunday? Add 24hrs
target += 24;
despatchday = 'on Monday';
} //keep this before the saturday, trust me :>
if (weekday == 6) { //It's Saturday? Add 48hrs
target += 48;
despatchday = 'on Monday';
}
if ((weekday == 5) && (now.getHours() > target) && (now.getHours() <= 24)) {
target += 72;
despatchday = 'on Monday';
}
//If between Monday and Friday,
//check if we're past the target hours,
//and if we are, abort.
if ((weekday >= 1) && (weekday <= 5)) {
if ((now.getHours() > target) && (now.getHours() <= 24)) { //stop the clock
target += 24;
despatchday = 'tomorrow';
} else if (now.getHours() > target) { //stop the clock
return 0;
despatchday = 'today';
}
}
var hrs = (target) - now.getHours();
if (hrs < 0) hrs = 0;
var mins = 59 - now.getMinutes();
if (mins < 0) mins = 0;
var secs = 59 - now.getSeconds();
if (secs < 0) secs = 0;
var str = 'Order in the next ' + hrs + 'hrs ' + mins + 'mins ' + secs + 'secs for despatch ' + despatchday;
document.getElementById('countdownTimer').innerHTML = str;
}, 1000
);
The problem I have is that if I set the cut off time to anything other than a full hour the timer does not work.
The correct output is Order in the next xx hrs, xx mins xx secs for despatch today
If I set
var target = 14; // This is the cut-off point
as 14:30 it gives "Just checking the time"
I assumed that it needed the mins as a decimal but if I set it as 14.5 it is adding 0.5 hrs to the output; ie 23.5hrs 50mins 30secs
I have set up a fiddle here. http://jsfiddle.net/4eu4o6k0/
Ideally I need it to be able to handle time in the format of hh:mm as that is the format of the time stored in the database. Is there a correct way to process partial hours in this type of script?
you need to hand the decimal place of hrs:
var rem =hrs%1;
mins = mins + (rem*60);
hrs = hrs - rem;
if (mins > 59) {
mins = mins - 60;
hrs= hrs +1;
}
Also I think you meant to spell dispatch
I'd personally advise against writing own code for handling time intervals because it's known to be error-prone. Use moment.js or date.js for such things
Here's sample for Moment.js
Related
Hi I've been trying to take and work with some code that I can get partially working, I want a countdown that we can set an end time it counts down to (obvious is obvious out of the way), we also want to set it to show at only certain times of the day and only certain days of the week.
I've managed to get the below working so we can set a time of the day to show but I can't get it to work so it only shows on the certain specified days. Can anyone help please?
var countdownMessage = "This ends in";
var now = new Date();
var time = now.getTime(); // time now in milliseconds
var countdownEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 12, 59); // countdownEnd 0000 hrs
//////////////////////////* Countdown *///////////////////////////////
function getSeconds() {
var ft = countdownEnd.getTime() + 86400000; // add one day
var diff = ft - time;
diff = parseInt(diff / 1000);
if (diff > 86400) {
diff = diff - 86400
}
startTimer(diff);
}
var timeInSecs;
var ticker;
function startTimer(secs) {
timeInSecs = parseInt(secs);
ticker = setInterval("tick()", 1000);
tick(); // to start counter display right away
}
function tick() {
var secs = timeInSecs;
if (secs > 0) {
timeInSecs--;
} else {
clearInterval(ticker); // stop counting at zero
//getSeconds(); // and start again if required
}
var hours = Math.floor(secs / 3600);
secs %= 3600;
var mins = Math.floor(secs / 60);
secs %= 60;
var result = ((hours < 10) ? "0" : "") + hours + " hours " + ((mins < 10) ? "0" : "") + mins + " minutes " + ((secs < 10) ? "0" : "") + secs + " seconds";
document.getElementById("countdown").innerHTML = (countdownMessage) + " " + result;
}
///////////////* Display at certain time of the day *//////////////////
//gets the current time.
var d = new Date();
if (d.getHours() >= 7 && d.getHours() <= 15) {
$("#countdown").show();
} else {
$("#countdown").hide();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<body onload="getSeconds()">
<span id="countdown" style="font-weight: bold;"></span>
</body>
[EDIT]
Just to add to this I tried changing part of the script to this but it didn't work:
$(function() {
$("#countdown").datepicker(
{ beforeShowDay: function(day) {
var day = day.getDay();
if (day == 1 || day == 2) {
//gets the current time.
var d = new Date();
if(d.getHours() >= 7 && d.getHours() <= 10 ){
$("#countdown").show();
}
else {
$("#countdown").hide();
}
} else {
$("#countdown").hide();
}
}
});
});
Whatever you did is all good except the setInterval part where you are passing the string value as setInterval("tick()", 1000) instead of a function reference as setInterval(tick, 1000)
Also, I have updated the code as below to check the specific day along with specific hours which you had,
var d = new Date();
var day = d.getDay();
if (day == 0 || day == 6) {
if (d.getHours() >= 0 && d.getHours() <= 8) {
$("#countdown").show();
} else {
$("#countdown").hide();
}
}
You can give a try below,
var countdownMessage = "This ends in";
var now = new Date();
var time = now.getTime(); // time now in milliseconds
var countdownEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 12, 59); // countdownEnd 0000 hrs
//////////////////////////* Countdown *///////////////////////////////
function getSeconds() {
var ft = countdownEnd.getTime() + 86400000; // add one day
var diff = ft - time;
diff = parseInt(diff / 1000);
if (diff > 86400) {
diff = diff - 86400
}
startTimer(diff);
}
var timeInSecs;
var ticker;
function startTimer(secs) {
timeInSecs = parseInt(secs);
ticker = setInterval(tick, 1000);
tick(); // to start counter display right away
}
function tick() {
var secs = timeInSecs;
if (secs > 0) {
timeInSecs--;
} else {
clearInterval(ticker); // stop counting at zero
//getSeconds(); // and start again if required
}
var hours = Math.floor(secs / 3600);
secs %= 3600;
var mins = Math.floor(secs / 60);
secs %= 60;
var result = ((hours < 10) ? "0" : "") + hours + " hours " + ((mins < 10) ? "0" : "") + mins + " minutes " + ((secs < 10) ? "0" : "") + secs + " seconds";
document.getElementById("countdown").innerHTML = (countdownMessage) + " " + result;
}
$("#countdown").hide();
///////////////* Display at certain time of the day *//////////////////
//gets the current time.
var d = new Date();
var day = d.getDay();
if (day == 0 || day == 6) {
if (d.getHours() >= 0 && d.getHours() <= 8) {
$("#countdown").show();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<body onload="getSeconds()">
<span id="countdown" style="font-weight: bold;"></span>
</body>
Found this daily countdown timer and edited it a little but I find it a little long and learned that Jquery is a shorter notation of javascript but don't know anything about it.
My knowledge is not advanced enough to either shorten this or change it to jquery.
I use the <body onload = "getSeconds()"> to start the daily countdown.
var reloadPage = false;
function getSeconds()
{
var now = new Date();
var time = now.getTime(); // time now in milliseconds
var midnight = new Date(now.getFullYear(),now.getMonth(),now.getDate(),21,57,0); //midnight 0000 hrs
//midnight - change time hh,mm,ss to whatever time required, e.g. 7,50,0 (0750)
var ft = midnight.getTime() + 86400000; // add one day 86 400 000
var diff = ft - time;
diff = parseInt(diff/1000);
if (diff > 86400) {diff = diff - 86400}
startTimer (diff);
}
var timeInSecs;
var ticker;
function startTimer(secs){
timeInSecs = parseInt(secs);
ticker = setInterval("tick()",1000);
tick(); //to start counter display right away
}
function tick() {
var secs = timeInSecs;
if (secs > 0) {
timeInSecs--;
}
else
{
clearInterval(ticker); //stop counting at zero
if (secs == 0)
{
reloadPage = true;
console.log("reset");
};
getSeconds(); //and start again if required
}
var hours= Math.floor(secs/3600);
secs %= 3600;
var mins = Math.floor(secs/60);
secs %= 60;
if(reloadPage)
{
var result = "Please reload page for daily reset."
}
else
{
var result = ((hours <= 0 ) ? "" : hours + " hours ") + ( (mins <= 0) ? "" : mins + " minutes " ) + ( (mins <= 0) ? " < 1 minute " : "" );
}
document.getElementById("countdown").innerHTML = "Daily reset: " + result;
}
Here's your code "changed to jQuery"
var reloadPage = false;
function getSeconds()
{
var now = new Date();
var time = now.getTime(); // time now in milliseconds
var midnight = new Date(now.getFullYear(),now.getMonth(),now.getDate(),21,57,0); //midnight 0000 hrs
//midnight - change time hh,mm,ss to whatever time required, e.g. 7,50,0 (0750)
var ft = midnight.getTime() + 86400000; // add one day 86 400 000
var diff = ft - time;
diff = parseInt(diff/1000);
if (diff > 86400) {diff = diff - 86400}
startTimer (diff);
}
var timeInSecs;
var ticker;
function startTimer(secs){
timeInSecs = parseInt(secs);
ticker = setInterval("tick()",1000);
tick(); //to start counter display right away
}
function tick() {
var secs = timeInSecs;
if (secs > 0) {
timeInSecs--;
}
else
{
clearInterval(ticker); //stop counting at zero
if (secs == 0)
{
reloadPage = true;
console.log("reset");
};
getSeconds(); //and start again if required
}
var hours= Math.floor(secs/3600);
secs %= 3600;
var mins = Math.floor(secs/60);
secs %= 60;
if(reloadPage)
{
var result = "Please reload page for daily reset."
}
else
{
var result = ((hours <= 0 ) ? "" : hours + " hours ") + ( (mins <= 0) ? "" : mins + " minutes " ) + ( (mins <= 0) ? " < 1 minute " : "" );
}
$("#countdown").html("Daily reset: " + result);
}
saving 27 bytes ... I'm sure loading 86000+ bytes of jQuery library wont negate this saving at all
a shorter implementation, imo. simpler, and no need for jQuery (even if you've already loaded it)
//a few values that come in handy when dealing with timestamps
MILLISECOND = MILLISECONDS = 1;
SECOND = SECONDS = 1000*MILLISECONDS;
MINUTE = MINUTES = 60*SECONDS;
HOUR = HOURS = 60*MINUTES;
DAY = DAYS = 24*HOURS;
TIMEZONE_OFFSET = new Date().getTimezoneOffset() * MINUTES;
var midnight = Date.now() + DAY - (Date.now() - TIMEZONE_OFFSET) % DAY;
function updateCountdown(){
//an utility to fetch the parts (hours, mins, ...) of the time
//and return a formated output
function fetch(factor, postfix){
var value = Math.floor(t/factor);
t %= factor; //beware: side-effect
//format the value
return value > 0?
value + (postfix == null? "": postfix):
"";
}
var t = midnight - Date.now(); //time till midnight
var countdown = document.querySelector("#countdown");
if(t <= 0){
countdown.innerHTML = "Please reload page for daily reset.";
location.reload();
}else{
countdown.innerHTML = [
"Daily reset:",
fetch(HOURS, " hours"),
fetch(MINUTES, " minutes"),
fetch(SECONDS, " seconds")
].join(" ");
setTimeout(updateCountdown, 200);
}
}
updateCountdown();
Edit:
how would I change the time to be resetted at
the variable midnight holds the target-timestamp I am counting to: t = midnight-Date.now()
change the target timestamp.
//a utility that gives you the timestamp for today `00:00 AM` (in your local timezone)
function today(){
var now = Date.now();
return now - (now - TIMEZONE_OFFSET) % DAY;
}
console.log( new Date( today() ) ); //today 00:00:00 GMT+yourTimeZoneOffset
define a target timezone:
var midnight = today() + 1*DAY;
var target = today() + 20*HOURS + 45*MINUTES + 59*SECONDS;
//you see how these constants get handy ;)
and compute the time to that target:
var t = target - Date.now();
the rest is the same
I am looking to show an estimated delivery date on the product page for each delivery option we have. I have read through the code in Shopify Variants by Steph Sharp which would work brilliantly except we would need it to be fixed to the current day up until 3pm and then switch to the next working day after 3pm. (Basically taking away the option for the customer to choose the dispatch day.)
I can’t quite get it to work by butchering this code into our template. This is what I have butchered together which seems to work okay but rather than have MON, TUE, WED, … I want to set them as the future dates. Any advice?
EDIT: Also I heard Palec is after using a timer code with this code too. So I will add that in.
<script language="JavaScript">
function day(a) {
var date = new Date();
var days = ["Mon","Tue","Wed","Thur","Fri","Mon","Tue","Wed","Thur","Fri","Mon","Tue","Wed","Thur","Fri"];
var today = date.getDay();
if (today == 1) today = 0; //Monday
if (today == 2) today = 1; //Tuesday
if (today == 3) today = 2; //Wednesday
if (today == 4) today = 4; //Thursday
if (today == 5) today = 5; //Friday
if (today == 6) today = -1; //Saturday Moved To Monday
if (today == 0) today = -1; //Sunday Moved To Monday
h = date.getHours();
if (h <= 9) h = "0" + h;
time = h;
if (time > 15) today++;
var expected = today + a;
var main = days[expected];
document.write('STANDARD DELIVERY ESTIMATE: ');
document.write(main);
}
</script>
<body>
<script language="JavaScript">
day(1)
</script>
I would try something like this:
function day(a) {
var date = new Date();
var hours = date.getHours();
// If after 3pm, add 1 day
if(hours > 15) a++;
var expectedDeliveryDate = addWeekdays(date, a);
document.write(expectedDeliveryDate.toDateString() + ' with Standard Delivery');
}
function addWeekdays(fromDate, days) {
var count = 0;
while (count < days) {
fromDate.setDate(fromDate.getDate() + 1);
if (fromDate.getDay() != 0 && fromDate.getDay() != 6) // Skip weekends
count++;
}
return fromDate;
}
(The code in the addWeekdays function is from this answer on Stack Overflow.)
This code just displays the day name (like the code in your question), but you can format expectedDeliveryDate however you want.
EDIT: I updated my code to use expectedDeliveryDate.toDateString() as specified in the comments. Note that you no longer need the days array or expectedDeliveryDay variable. (You've still got them in your answer but they're not being used.)
This is my final code, based on Steph Sharp’s answer.
function day(a) {
var date = new Date();
var hours = date.getHours();
// If after 3pm, add 1 day
if (hours >= 15) a++;
var expectedDeliveryDate = addWeekdays(date, a);
document.write(expectedDeliveryDate.toDateString() + ' with Standard Delivery');
}
function addWeekdays(fromDate, days) {
var count = 0;
while (count < days) {
fromDate.setDate(fromDate.getDate() + 1);
if (fromDate.getDay() != 0 && fromDate.getDay() != 6) // Skip weekends
count++;
}
return fromDate;
}
Also added a timer:
function ShowTime() {
var now = new Date();
var hrs = 15 - now.getHours();
if (hrs < 0) hrs += 24;
var mins = 60 - now.getMinutes();
var secs = 60 - now.getSeconds();
timeLeft = "" + hrs + ' hours ' + mins + ' minutes ' + secs + ' seconds';
$("#countdown").html(timeLeft);
}
var countdown = setInterval(ShowTime, 1000);
function StopTime() {
clearInterval(countdown);
}
Let me first say I do not have a deep understanding of javascript but I know how to work my way around enough to write small scripts for pages. A client of mine needs me to do the following for a website:
Find the user's local time on their computer.
Take that local time and subtract it from 6pm.
Display that time in a countdown or just a statement letting the user know how much time is left for same day shipping.
After 6pm the time resets or disappears until the next business day.
So far I've been able to create the logic for getting the time from the local computer. I thought I'd be able to use datejs but it does not calculate hours in a day.
Here is the current code I have:
var currentTime = new Date()
var hours = currentTime.getHours()
var minutes = currentTime.getMinutes()
var suffix = "AM";
if (hours >= 12)
{
suffix = "PM";
hours = hours - 12;
}
var suffix = "AM";
if (hours >= 12)
{
suffix = "PM";
hours = hours - 12;
}
if (hours == 0)
{
hours = 12;
}
if (minutes < 10)
minutes = "0" + minutes;
document.write("<b>" + hours + ":" + minutes + " " + suffix + "</b>");
How about this:
var currentTime = new Date()
var hours = currentTime.getHours()
var minutes = currentTime.getMinutes()
var suffix = "AM";
if (hours >= 12) {
suffix = "PM";
hours = hours - 12;
}
if (minutes < 10)
minutes = "0" + minutes
if (suffix == "PM" && hours >= 6)
{
document.write("You're too late for next day shipping!");
}
else
{
var hoursLeft = 5 - hours;
var minsLeft = 60 - minutes;
document.write("<b> You've got " + hoursLeft + " hours and " + minsLeft + " minutes left to qualify for next day shipping! </b>")
}
if this site would let me comment on other people's answers I'd give the credit for this to Giovanni, but since I can't yet comment on other people's work, here's what needs to change.
var currentTime = new Date()
var hours = currentTime.getHours()
var minutes = currentTime.getMinutes()
var suffix = "AM";
if (minutes < 10)
minutes = "0" + minutes
if (hours >= 18)
{
document.write("You're too late for next day shipping!");
}
else
{
var hoursLeft = 17 - hours;
var minsLeft = 60 - minutes;
if(minsLeft==60){
minsLeft=0;
hoursLeft++;
}
document.write("<b> You've got " + hoursLeft + " and " + minsLeft + " minutes left to qualify for next day shipping! </b>")
}
The reason for this is that people who are ordering at 5AM might see think that they have to submit within the next hour for their shipping to be next day when in fact they have the next 13 hours.
EDIT: saw your timezone concern and here is a post that might interest you.
EDIT 2: posted the wrong link. The correct one should be up now, though it might be a bit of a dated answer.
Something similar I solved also yesterday, so this is easy. Here is the javascript code:
function start_onload(last_hour){
var timeout_message = document.getElementById('timeout_message');
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
var seconds = currentTime.getSeconds();
var expire_time = 0; // in seconds
if (hours<last_hour) {
expire_time += (last_hour-hours-1)*3600;
expire_time += (59-minutes)*60;
expire_time += (59-seconds);
}
else {
timeout_message.innerHTML = 'It\'s after '+last_hour+' o\'clock!';
return;
}
var expire_time = currentTime.getTime() + 1000*expire_time;
//console.log(expire_time, hours, minutes, seconds, expire_time);
function countdown_session_timeout() {
var current_time = new Date().getTime();
var remaining = Math.floor((expire_time - current_time)/1000);
if (remaining>0) {
hours = Math.floor(remaining/3600);
minutes = Math.floor((remaining - hours*3600)/60);
seconds = remaining%60;
timeout_message.innerHTML = 'Countdown will stop in '+ hours + ' hours ' + minutes + ' min. ' + seconds + ' sec.';
setTimeout(countdown_session_timeout, 1000);
} else {
timeout_message.innerHTML = 'Time is up!';
}
}
countdown_session_timeout();
}
Full script # pastebin.com is here.
This is a simple countdown timer starting at 30 seconds from when the function is run and ending at 0. After reaching 0 it automatically reset the counter. It goes again to 30 second and this process is continued in a loop
window.onload = function() { startCountDown(30,
1000, myFunction); }
function startCountDown(i, p, f) { var pause = p; var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
//write out count
countDownObj.innerHTML = i;
if (i == 0) {
//execute function
//fn();
startCountDown(30, 1000, myFunction); //stop
return; } setTimeout(function() {
// repeat
countDownObj.count(i - 1);
},
pause
); } //set it going countDownObj.count(i); }
function myFunction(){};
</script>
I have two sets of 'select' elements where the user can enter in two times. It looks like this:
Start:
[hour] [minute] [meridian]
End:
[hour] [minute] [meridian]
I'm trying to take those times and figure out the difference. So I can then output:
Difference: 1.25 HRS
The decimal format, as you probably know, means 1 hour and 15 minutes.
There's also a checkbox the user can click which, if selected, will take away 30 minutes. Here's what my current code looks like:
var startHours = parseInt($start.find('.times:eq(0)')[0].value);
var startMinutes = parseInt($start.find('.times:eq(1)')[0].value);
var startMeridian = $start.find('.times:eq(2)')[0].value
if (startMeridian == 'PM')
startHours += 12;
var finishHours = parseInt($finish.find('.times:eq(0)')[0].value);
var finishMinutes = parseInt($finish.find('.times:eq(1)')[0].value);
var finishMeridian = $finish.find('.times:eq(2)')[0].value
if (finishMeridian == 'PM')
finishHours += 12;
// compute the difference
var completeHours = finishHours - startHours;
var completeMinutes = finishMinutes - startMinutes;
var newTime = 0;
if (completeHours < 0 || completeMinutes < 0)
newTime = '0.0';
else
newTime = completeHours + '.' + completeMinutes;
var hadBreak = $parent.parents('tr').next('tr').find('.breakTaken')[0].checked;
if (hadBreak)
{
time = newTime.split('.');
hours = time[0];
minutes = time[1];
minutes = minutes - 30;
if (minutes < 0)
{
minutes = 60 - (minutes * 1);
hours = hours - 1;
}
newTime = (hours < 0) ? '0.0' : hours + '.' + minutes;
}
$parent.parents('tr').next('tr').find('.subtotal')[0].innerHTML = newTime;
total += parseFloat(newTime);
It's failing... What am I doing wrong?
To save you some hassle, I would recommend using the Date object, which is very convenient:
var startDate = new Date(year, month, date, hour, minute, second, millisecond);
var endDate = new Date(year, month, date, hour2, minute2, second2, millisecond2);
// You can skip hours, minutes, seconds and milliseconds if you so choose
var difference = endDate - startDate; // Difference in milliseconds
From there you can calculate the days, hours and minutes that passed between those two dates.
The line
newTime = (hours < 0) ? '0.0' : hours + '.' + minutes;
is wrong - minutes might be 15, but you want it to print out the fraction. Hence you need:
var MinutesDisplay = minutes/60*100;
newTime = (hours < 0) ? '0.0' : hours + '.' + (MinutesDisplay.toFixed(0));