Skip to content

Instantly share code, notes, and snippets.

@steven-prybylynskyi
Last active October 3, 2017 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steven-prybylynskyi/a2e92f2cb7183ade043061a97ad10372 to your computer and use it in GitHub Desktop.
Save steven-prybylynskyi/a2e92f2cb7183ade043061a97ad10372 to your computer and use it in GitHub Desktop.
moment.js - show recurring remaining time (requires jQuery and Lodash)
<script src="//cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
<script src="//code.jquery.com/jquery-2.2.4.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<div
id="countdownTimer"
data-end-date="01-01-2020"
data-end-time="13:00:00"
data-days-of-week="[1,2,3,4,5]"
data-exclude-dates="['31-12', '1-01']"
>
<span class="days"></span> day(s)
<span class="hours"></span>h
<span class="minutes"></span>min
<span class="seconds"></span>sec
time remains till next shipping
</div>
<style>
#countdownTimer {
display: none;
}
</style>
<!-- Show how much days and time left till next shipping day every Monday excluding holidays -->
<script>$(function() {
var $clock = $('#countdownTimer');
var endDate = $clock.data('endDate') || '01-01-2020'; // dd:mm:yyyy
var endTime = $clock.data('endTime') || '13:00:00'; // hh:mm:ss
var excludeDates = (new Function('return ' + $clock.data('excludeDates')))() || [];
var daysOfWeek = $clock.data('daysOfWeek') || [1, 2, 3, 4, 5, 6, 7];
showRemaining($clock, 'DD-MM-YYYY', endDate, endTime, daysOfWeek, excludeDates);
/**
* Show remaining days and time
*
* @param {jQuery} $clock Container for remaining days/time elements
* Should contain 4 elements with corresponding classes:
* days, hours, minutes and seconds
*
* @param {Object} dateFormat Localized date format, e.g. DD.MM.YYYY in Denmark
* @param {Object} endDate Last date of schedule
* @param {number} endTime Time in `HH:mm:ss` format
* @param {Array} daysOfWeek Days on which the event will happen
* @param {Array} excludeDates Dates to ignore
*/
function showRemaining($clock, dateFormat, endDate, endTime, daysOfWeek, excludeDates) {
var currentTimeObj = moment();
var eventTimeObj = getNextMatchingDate(daysOfWeek, currentTimeObj, endTime);
while (matchesDate(excludeDates, eventTimeObj, dateFormat)) {
currentTimeObj = currentTimeObj.add(1, 'day');
eventTimeObj = getNextMatchingDate(daysOfWeek, currentTimeObj, endTime);
}
var endTimeObj = moment(endDate + ' ' + endTime, dateFormat + ' HH:mm:ss');
var diffEndTime = endTimeObj.unix() - eventTimeObj.unix();
// Check if current date/time have past the end date
if (diffEndTime < 0) {
return;
}
var diffTime = eventTimeObj.unix() - currentTimeObj.unix();
var remaining = moment.duration(diffTime * 1000, 'milliseconds');
var interval = 1000;
var $d = $clock.find('.days');
var $h = $clock.find('.hours');
var $m = $clock.find('.minutes');
var $s = $clock.find('.seconds');
// Show clock
setTimeout(function() {
$clock.show();
}, interval);
setInterval(function() {
// Update remaining time
remaining = moment.duration(remaining.asMilliseconds() - interval, 'milliseconds');
// Show how many hours, minutes and seconds are left
$d.text(remaining.days());
$h.text(_.padStart(remaining.hours(), 2, '0'));
$m.text(_.padStart(remaining.minutes(), 2, '0'));
$s.text(_.padStart(remaining.seconds(), 2, '0'));
}, interval);
}
/**
* @param {Array} daysOfWeek
* @param {Object} currentTimeObj
* @param {string} endTime
*
* @return {Object}
*/
function getNextMatchingDate(daysOfWeek, currentTimeObj, endTime) {
// Whether event time is in past related to current time
var isPastEventTime = (moment(endTime, 'HH:mm:ss').unix() - moment().unix() < 0);
var currentDayOfWeek = currentTimeObj.day();
var matchingDayOfWeek = _.find(daysOfWeek, function(dayOfWeek) {
var diffDays = dayOfWeek - currentDayOfWeek;
if (diffDays > 0 || (diffDays === 0 && !isPastEventTime)) {
return dayOfWeek;
}
});
matchingDayOfWeek = matchingDayOfWeek || _.min(daysOfWeek);
if (matchingDayOfWeek - currentDayOfWeek < 0) {
// Sunday + next week's clothest day
matchingDayOfWeek = 7 + _.min(daysOfWeek);
}
var eventTimeObj = moment(endTime, 'HH:mm:ss').day(matchingDayOfWeek);
return eventTimeObj;
}
/**
* Match date in dates array
*
* @param {string[]} dates
* @param {Object} dateMatchObj
* @param {string} dateFormat
*/
function matchesDate(dates, dateMatchObj, dateFormat) {
return dates.some(function(dateNext) {
var dateNextObj = moment(dateNext, dateFormat);
return (dateNextObj.month() === dateMatchObj.month()) && (dateNextObj.date() === dateMatchObj.date());
});
}
});</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment