PNewCode Posted July 16, 2023 Share Posted July 16, 2023 Hello I hope everyone is having an awesome day! I have a nifty little countdown script that works how it's intended. I bought this from someone (only to find out he just copied and pasted it from a site that had it free) so he doesn't know how to alter it. I am VERY brand new to JS and while what I have makes sense to me, I lack the understanding on how to make this work, despite all the studying I've got done So here is what I want to make happen (this is day 3 on this and I can't find a clear solution) In my database table, I have "duration" and "created_at" columns (there are other columns but it's just other info) This is entered from a form that is set up to start an auction. It successfully enters the time stamp (for example: 2023-07-16 12:45:00) and the duration is entered successfully too (for example: 30). This number for the duration is entered to set up different lengths of time that the auction will run (sometimes 10 min sometimes 30, etc) What I can't seem to make happen and trying is 2 things 1: Make the timer work with adding whatever is in the duration to the timestamp time, to make that count down. 2: Different time zones show different time remaining (Because the timestamp). So I need a way to have it adjusted to the viewers timezone when seeing this Here is the full page of what I have. You'll notice that "duration" isn't in the js right now, but I couldn't get it to work with it. I'm stuck like a fly on maple syrup BONUS THANKS if you can also tell me how to change the font color of the displaying "minutes, hours, seconds" text <?php error_reporting(E_ALL); ini_set('display_errors', '1'); $mysqli = new mysqli(connection info deleted for posting); if ($mysqli -> connect_errno) { echo "Failed to connect to MySQL: " . $mysqli -> connect_error; exit(); } $sql = "SELECT * FROM auctiontitle"; if ($result = $mysqli -> query($sql)) { while($row = $result->fetch_assoc()) { $duration = $row["duration"]; $created_at = $row["created_at"]; $date = "$created_at"; } } else { echo "0 results"; } ?> <body marginwidth="0" marginheight="0"> <div align="center"> <font size="4"><b><font face="Verdana, Arial, Helvetica, sans-serif" color="#CCCCFF"> <div id="data" align="center"></div> <input type="hidden" id="date" value="<?php echo $date; ?>"> <script> function func() { var dateValue = document.getElementById("date").value; var date = Math.abs((new Date().getTime() / 1000).toFixed(0)); var date2 = Math.abs((new Date(dateValue).getTime() / 1000).toFixed(0)); var diff = date2 - date; var days = Math.floor(diff / 86400); var hours = Math.floor(diff / 3600) % 24; var minutes = Math.floor(diff / 60) % 60; var seconds = diff % 60; var daysStr = days; if (days < 10) { daysStr = "0" + days; } var hoursStr = hours; if (hours < 10) { hoursStr = "0" + hours; } var minutesStr = minutes; if (minutes < 10) { minutesStr = "0" + minutes; } var secondsStr = seconds; if (seconds < 10) { secondsStr = "0" + seconds; } if (days < 0 && hours < 0 && minutes < 0 && seconds < 0) { daysStr = "00"; hoursStr = "00"; minutesStr = "00"; secondsStr = "00"; console.log("close"); if (typeof interval !== "undefined") { clearInterval(interval); } } document.getElementById("data").innerHTML = hoursStr + " Hours & " + minutesStr + " Minutes & " + secondsStr + " Seconds"; } func(); var interval = setInterval(func, 1000); </script> </font></b></font></div> Quote Link to comment Share on other sites More sharing options...
Barand Posted July 16, 2023 Share Posted July 16, 2023 Does this thread help? ... Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 16, 2023 Author Share Posted July 16, 2023 @Barand I love the look of that! Very nice and fancy. However it doesn't work right. When I changed the target timestamp to 2023-07-16 18:45:00 that should have around 5 hours, 45min left, but it shows there's only an hour remaining. So if that is to detect time zones then it doesn't work right. But thank you for the post it's very nice looking This is what it shows on the page (it's 1pm here) Quote Link to comment Share on other sites More sharing options...
Strider64 Posted July 16, 2023 Share Posted July 16, 2023 (edited) I do it a little different way - I do all the time figure in JavaScript (I use Vanilla JavaScript) -> "use strict"; // Function to calculate the time remaining till a certain end time const getTimeRemaining = (countdown_date) => { // Parse the end time and current time into milliseconds const endtimeParsed = Date.parse(countdown_date); const nowParsed = Date.parse(new Date()); // Calculate the total remaining time in milliseconds const total = endtimeParsed - nowParsed; // Breakdown the total time into days, hours, minutes, and seconds const seconds = Math.floor((total / 1000) % 60); const minutes = Math.floor((total / 1000 / 60) % 60); const hours = Math.floor((total / (1000 * 60 * 60)) % 24); const days = Math.floor(total / (1000 * 60 * 60 * 24)); // Return a time object that has the total remaining time and the breakdown return { total, days, hours, minutes, seconds }; }; // Function to display a countdown clock on the webpage const myClock = (id, countdown_date) => { // Find the clock and its components by their IDs const clock = document.getElementById(`display_clock${id}`); const daysSpan = clock.querySelector(`.day${id}`); const hoursSpan = clock.querySelector(`.hour${id}`); const minutesSpan = clock.querySelector(`.minute${id}`); const secondsSpan = clock.querySelector(`.second${id}`); // Function to update the clock display const updateClock = () => { // Get the remaining time const time = getTimeRemaining(countdown_date); // Update the display of each component of the clock // padStart() is used to ensure that all components are two digits daysSpan.textContent = time.days; hoursSpan.textContent = String(time.hours).padStart(2, '0'); minutesSpan.textContent = String(time.minutes).padStart(2, '0'); secondsSpan.textContent = String(time.seconds).padStart(2, '0'); // If the total remaining time is zero or less, stop the clock by clearing the interval if (time.total <= 0) { clearInterval(timeInterval); } } // Call updateClock once immediately, then at regular intervals updateClock(); const timeInterval = setInterval(updateClock, 1000); }; function fetchRoutine() { // Define the data you want to send to the server const grabDate = "myDate=endDate"; // Define the options for the fetch call const fetchOptions = { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' }, body: grabDate }; // Make the fetch call fetch('countdown_date.php', fetchOptions) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } // If the response was ok, proceed to parse it as JSON return response.json(); }) .then(data => { console.log('data', data); document.getElementById("countdown_date").textContent = data.date_format; document.getElementById("display_title").textContent = data.title; let countdown_date = new Date(Date.parse(data.time_left)); myClock(1, countdown_date); }) .catch(error => { console.error('There has been a problem with your fetch operation:', error); }); } fetchRoutine(); Here's the HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Countdown Clock</title> <link rel="stylesheet" href="reset.css"> <link rel="stylesheet" href="countdown.css"> </head> <body> <div class="info"> <h1 id="display_title"></h1> <h2 id="countdown_date"></h2> </div> <div id="display_clock1"> <figure class="box"> <div class="day1"></div> <figcaption>Days</figcaption> </figure> <figure class="box"> <div class="hour1"></div> <figcaption>Hours</figcaption> </figure> <figure class="box"> <div class="minute1"></div> <figcaption>Minutes</figcaption> </figure> <figure class="box"> <div class="second1"></div> <figcaption>Seconds</figcaption> </figure> </div> <script src="count_down.js"></script> </body> </html> and the css *{ -webkit-box-sizing: border-box; box-sizing: border-box; } div.info { display: block; width: 100%; max-width: 300px; height: auto; text-align: center; padding: 2px; margin: 10px auto; } div.info::after { content: ''; display: block; clear: both; } h1 { font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif; font-size: 1.2em; line-height: 1.5; } h2 { font-family: Arial, Helvetica, sans-serif; font-size: 1.0em; font-style: italic; font-weight: 300; } div#display_clock1 { display: block; width: 100%; max-width: 190px; height: auto; margin: 5px auto; background-color: pink; } div#display_clock1 figure.box { float: left; display: block; width: 100%; max-width: 40px; height: 70px; color: #fff; text-align: center; padding: 0; margin-left: 5px; } div#display_clock1 figure.box div { background-color: #2e2e2e; height: 50px; line-height: 50px; } div#display_clock1 figure.box figcaption { font-family: Arial, Helvetica, sans-serif; font-size: 0.6em; line-height: 20px; font-weight: bold; color: #000; } it's an old script that I made changes to, so it used a little PHP <?php header('Content-type: application/json'); $endDate = filter_input(INPUT_POST, 'myDate'); if ($endDate === 'endDate') { $count_down_date = new DateTime('2023-07-17 00:00:00', new DateTimeZone("America/Detroit")); $data['time_left'] = $count_down_date->format("Y/m/d H:i:s"); $data['date_format'] = $count_down_date->format("l - F j, Y"); $data['title'] = "Countdown to "; output($data); } function errorOutput($output, $code = 500) { http_response_code($code); echo json_encode($output); } /* * If everything validates OK then send success message to Fetch / JavaScript */ function output($output) { http_response_code(200); echo json_encode($output); } This could be done in JavaScript or even pulling from a Database Table. Like I said it's an old script that I modernized it a little. Edited July 16, 2023 by Strider64 Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 16, 2023 Author Share Posted July 16, 2023 (edited) @Strider64 Thank you very much, though I don't need the count down function. I already have one that grabs the date from the database and counts down. Thank you for sharing that though. The trouble I'm having is adding the time from $duration to the timestamp in $created_at The reason I have this is because on the form to submit the auction, it has "How long do you want to run the auction" and you type X amount of minutes. That value goes to $duration I figured out how to get it to add a certain amount of time each time, for example the following will add 10 min, and the countdown timer that I have will count down from 10 minutes $date = date('Y-m-d H:i:s', strtotime('+10 minute')); And then I put $date into the "created_at" column And so far this works great. Buuuutttttt... if I want to do an auction where I want it to run for 30 minutes, then I have to go in and change the file each time and reupload it. Which isn't an option when I have to use this auction several times in a 4 hour period. I tried putting in $duration instead of +10 minute several times but that didn't work either (btw in the column $duration, the value is "+30 min" or whatever amount of min I enter) It puzzles me that this doesn't work $date = date('Y-m-d H:i:s', strtotime('$duration')); When the value says "+30 minute" in the database. Makes no sense to me at all EDIT: This post is a follow up from the original to show how the date and time gets entered in the database because I gave up trying to do it with only just the first original post so I added this to the part that puts the info in the database. Edited July 16, 2023 by PNewCode Quote Link to comment Share on other sites More sharing options...
Barand Posted July 16, 2023 Share Posted July 16, 2023 19 minutes ago, PNewCode said: It puzzles me that this doesn't work $date = date('Y-m-d H:i:s', strtotime('$duration')); When the value says "+30 minute" in the database. Because you put the $duration inside single quotes it is treating it as the string literal "$duration" and not "+30 minute". EG $duration = '+30 minute'; echo '$duration' . '<br>'; echo $duration . '<br>'; gives $duration +30 minute Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 (edited) @Barand $date = date('Y-m-d H:i:s', strtotime($duration)); That works. NOW the next trick to make it all awesome and stuff is to make this send as if the value is "+30 minute" if only 30 is entered. I can do that easliy to add to the database, however it has to pass from the form to the php page so it gets picked up in the $_POST <input type="text" name="duration" style="font-size:20pt;" required /> I tried to do an array like this but for the life of me I couldn't get it to work on the php page <input type="hidden" name="duration[]" value="+" required /> <input type="text" name="duration[]" style="font-size:20pt;" required /> <input type="hidden" name="duration[]" value=" minute" required /> and also tried this but I couldn't figure out a way to have it all in one line in the post <input type="hidden" name="duration2" value="+" required /> <input type="text" name="duration" style="font-size:20pt;" required /> <input type="hidden" name="duration3" value=" minute" required /> Because it HAS to pass in the very start of the php page in this line, in order for it to work for the time adjustment $duration = mysqli_real_escape_string($conn, $_POST['duration']); Right now I'm having to manually type +30 minute in the form field for all of this to work. It's rather annoying lol. Plus I see this being a problem if this gets ignored by users to type all that in. So.... trying to get it to work right. Also... I still don't know how to make it so the time translates to different timezones but I'll worry about that after I get this first part solved. SIDE NOTE: I just LOVE this site. I've learned so much. I'm absolutely addicted to creating new things for websites now Edited July 17, 2023 by PNewCode Quote Link to comment Share on other sites More sharing options...
Solution Barand Posted July 17, 2023 Solution Share Posted July 17, 2023 Keep it simple for the user with datetime and time input fields <form method='POST'> <label for='start'>Auction Start</label> <input type='datetime-local' name='start' id='start'> <br> <label for='duration'>Duration</label> <input type='time' name='duration' id='duration'> <br><br> <input type='submit'> </form> Store these values in your auction table CREATE TABLE `auction` ( +----+---------------------+----------+ `id` int(11) NOT NULL AUTO_INCREMENT, | id | start_time | duration | `start_time` datetime DEFAULT NULL, +----+---------------------+----------+ `duration` time DEFAULT NULL, | 1 | 2023-07-17 15:00:00 | 02:30:00 | PRIMARY KEY (`id`) | 2 | 2023-07-18 12:00:00 | 03:00:00 | ) ENGINE=InnoDB;</body> +----+---------------------+----------+ When you want the auction end time for your countdown, query the database and use sql's addtime() function... SELECT id , start_time as start , duration , addtime(start_time, duration) as finish FROM auction; +----+---------------------+----------+---------------------+ | id | start | duration | finish | +----+---------------------+----------+---------------------+ | 1 | 2023-07-17 15:00:00 | 02:30:00 | 2023-07-17 17:30:00 | | 2 | 2023-07-18 12:00:00 | 03:00:00 | 2023-07-18 15:00:00 | +----+---------------------+----------+---------------------+ Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 @Barand This looks like an excellent approach and much more simplified than what I'm doing. I need to ask though for clarity, would I also add a column for "finish"? Quote Link to comment Share on other sites More sharing options...
Barand Posted July 17, 2023 Share Posted July 17, 2023 1 minute ago, PNewCode said: would I also add a column for "finish"? No. Don't store derived data. If you have the start and duration then the finish is known . EG to find next, or current, auction SELECT id , start_time as start , duration , addtime(start_time, duration) as finish FROM auction WHERE addtime(start_time, duration) > NOW() order by start_time LIMIT 1; Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 @Barand thank you. I just got some coffee and I'm going to try this right now Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 @Barand You are quite amazing! I hope you know that!!! This simplified everything and works beautifully. Now I have to find a way to have the page that shows the timer, adjust to the viewers timezone so the counts down accurately. I just entered a test auction for 11 hours, my friend in Sweden shows 5 hours remaining. BUT this will give me something to do today haha. Thank you so much for your help!!! Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 Oops I meant to hit the other one you posted as the solution. Sorry Quote Link to comment Share on other sites More sharing options...
Barand Posted July 17, 2023 Share Posted July 17, 2023 3 minutes ago, PNewCode said: Oops I meant to hit the other one you posted as the solution. Sorry Fixed Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 17, 2023 Author Share Posted July 17, 2023 Thank you Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 18, 2023 Author Share Posted July 18, 2023 (edited) @Barand and others that see this. I don't know if I should make a new topic or not since I picked a solution, and I am worried that I may be an annoyance with all of my questions. But here I am on day 5 of this project and I can't get this last part resolved. Here is what I have, Thanks to you! 1: User creates an auction 2: The auction accepts or declines the offer based on if it's higher or lower than the highest bid 3: When it ends, a new screen appears showing it's ended and if the logged in user is the winner then they also see a button to pay for the auction via paypal 4: I have an edit auction page where I can adjust the time, image, name, etc Where I am stuck now is getting this timer to work for viewers in different time zones. It will be accurate in the time the user posted it, but not for others. For example, if I creat an auction to run for 10 hours, then it will show users in my time zone 10 hours remaining. However if someone in London views it then they see 5 hours remaining. This will cause the auction end to not be the same for everyone. I really do appreciate all the help, and again I've learned so much. This last peice of the puzzle has me stumped. HERE IS WHAT I'VE TRIED and what I think MIGHT work but haven't been able to get it right... In the JS countdown, I've tried adding UTC comments to the NEW TIME in various places and also added the months in the brackets. I've tried to create a part in the php section to convert it then use it (which I think may be the best approach but I can't figure it out) Finally, everything I see in my searches shows example of how to convert it if you put in a specific time zone (like if I manually put in America/Denver for example) but nothing that shows universal for everyone. Also, I can't seem to find a clear answer on if my timestamps are even being stored as UTC or not lol Here is what I have so for this now, all of this works perfect except for the timezone issue. THANK YOU SO MUCH! <?php error_reporting(E_ALL); ini_set('display_errors', '1'); $mysqli = new mysqli("deleted for posting","deleted for posting","deleted for posting","deleted for posting"); if ($mysqli -> connect_errno) { echo "Failed to connect to MySQL: " . $mysqli -> connect_error; exit(); } $sql = "SELECT * FROM auctiontitle"; if ($result = $mysqli -> query($sql)) { while($row = $result->fetch_assoc()) { $duration = $row["duration"]; $created_at = $row["created_at"]; $date = "$created_at"; } } else { echo "0 results"; } ?> <div id="data" align="center"></div> <input type="hidden" id="date" value="<?php echo $date; ?>"> <script> function func() { var dateValue = document.getElementById("date").value; var date = Math.abs((new Date().getTime() / 1000).toFixed(0)); var date2 = Math.abs((new Date(dateValue).getTime() / 1000).toFixed(0)); var diff = date2 - date; var days = Math.floor(diff / 86400); var hours = Math.floor(diff / 3600) % 24; var minutes = Math.floor(diff / 60) % 60; var seconds = diff % 60; var daysStr = days; if (days < 10) { daysStr = "0" + days; } var hoursStr = hours; if (hours < 10) { hoursStr = "0" + hours; } var minutesStr = minutes; if (minutes < 10) { minutesStr = "0" + minutes; } var secondsStr = seconds; if (seconds < 10) { secondsStr = "0" + seconds; } if (days < 0 && hours < 0 && minutes < 0 && seconds < 0) { window.location.href = "auction-ended.php","_blank"; daysStr = "00"; hoursStr = "00"; minutesStr = "00"; secondsStr = "00"; console.log("close"); if (typeof interval !== "undefined") { clearInterval(interval); } } document.getElementById("data").innerHTML = hoursStr + " Hours " + minutesStr + " Minutes " + secondsStr + " Seconds"; } func(); var interval = setInterval(func, 1000); </script> EDIT: This is what I'm thinking could work, but not sure how. Something like... ///// in the php section ///// $created_at = $row["created_at"]; $created_at = (something here that converts the time to the viewers timezone); $date = $created_at ///// then that could reflect the $date in the js countdown ///// Edited July 18, 2023 by PNewCode Quote Link to comment Share on other sites More sharing options...
PNewCode Posted July 18, 2023 Author Share Posted July 18, 2023 @Barand and others.... I DID IT YAY! Below is the solution (in case anyone else can learn from this too) I just changed the JS a bit and added a line to reflect the local time I had that adjusted var dateValue = document.getElementById("date").value; var dateValue2 = new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }); var date = Math.abs((new Date(dateValue2).getTime() / 1000).toFixed(0)); var date2 = Math.abs((new Date(dateValue).getTime() / 1000).toFixed(0)); Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.