1

EDIT: I eventually found the solution, posting here in case someone might find it useful. The short version is that JavaScript dates are a pain to work with.

ORIGINAL POST:

I'm making a web page that calculates whether or not it is recycling week, and if it is, which neighborhood is scheduled for pickup.

This demo uses the first day of a previously scheduled recycling week as the date of demarcation and counts in 14 day increments from that date. Every 14th day represents the start of a new recycling week. The message displayed changes depending on the time of day and what day of the week it is.

The issue I was running into was that the start date for the next recycling week would be incorrect for a few hours each day. I figured it was a time zone thing, but setting the time zone on the demarcation date produced the same result.

In the end I ended up changing the date format on the demarcation date and it worked.

I went from this...

var demarcationdate = new Date("2017-03-13");

...to this...

var demarcationdate= new Date("2017-03-13").toLocaleString("en-US", {timeZone: "America/New_York"});

...to this, which finally worked.

var demarcationdate = new Date("March 13, 2017 00:00:00");

Here's a link to the demo on CodePen: https://codepen.io/mikejandreau/pen/MxZmZq

The HTML:

<header class="masthead" id="map">
  <div class="container h-100">
    <div class="row h-100 align-items-center">
      <div class="col-12 text-center text-white">

        <h1 class="display-4 mb-4">
          <span id="greeting" class="greeting"></span>
        </h1>

        <p class="lead">
          <span id="todaysDate"></span>
          <span id="neighborhood"></span>
          <span id="futureDate"></span>
        </p>

        <p>
          <span id="followingWeek"></span>
        </p>

      </div>
    </div>
  </div>
</header>

The CSS (not really important, but here it is anyway):

#map {
  height: 100%;
  height: 100vh;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}

The JS:

// greeting based on time of day
var thehours = new Date().getHours();
var greeting = document.getElementById('greeting');
var themessage;
var morning = ('Good morning!');
var afternoon = ('Good afternoon!');
var evening = ('Good evening!');

if (thehours >= 0 && thehours < 12) {
  themessage = morning; 

} else if (thehours >= 12 && thehours < 17) {
  themessage = afternoon;

} else if (thehours >= 17 && thehours < 24) {
  themessage = evening;
}

greeting.innerHTML= themessage; // show greeting, always on


// neighborhood for day of week
var scheduleCurrentDate = new Date();
var scheduleAllDays = [
  {
    day: "Sunday",
    neighborhood: "recycling pickup is scheduled for the <strong>Fairmount Neighborhood</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Sunday+Image"
  },
  {
    day: "Monday",
    neighborhood: "recycling pickup is scheduled for the <strong>West Market Neighborhood</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Monday+Image"
  },
  {
    day: "Tuesday",
    neighborhood: "recycling pickup is scheduled for the <strong>Union Street Neighborhood</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Tuesday+Image"
  },
  {
    day: "Wednesday",
    neighborhood: "recycling pickup is scheduled for the <strong>Broadway and State Street Neighborhoods</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Wednesday+Image"
  },
  {
    day: "Thursday",
    neighborhood: "recycling pickup is scheduled for the <strong>Downtown Neighborhood</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Thursday+Image"
  },
  {
    day: "Friday",
    neighborhood: "recycling pickup is scheduled for the <strong>East Hills Neighborhood</strong>",
    image:
    "https://via.placeholder.com/1920x1080/555555/666666/?text=Friday+Image"
  },
  {
    day: "Saturday",
    neighborhood: "recycling pickup is scheduled for the <strong>Kenduskeag Neighborhood</strong>",
    image:
    "https://via.placeholder.com/450x800/555555/666666/?text=Saturday+Image"
  }
];

// document.getElementById("day").innerHTML = scheduleAllDays[scheduleCurrentDate.getDay()].day;
// document.getElementById("neighborhood").innerHTML = scheduleAllDays[scheduleCurrentDate.getDay()].neighborhood + " (excluding holidays). ";
document.getElementById("map").style.background =
  "url('" + scheduleAllDays[scheduleCurrentDate.getDay()].image + "') no-repeat center"; // show background image, based on day of the week



// calculate bi-weekly schedule
function treatAsUTC(date) {
    var result = new Date(date);
    result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
    return result;
}

function daysBetween(startDate, endDate) {
    var millisecondsPerDay = 24 * 60 * 60 * 1000;
    return Math.floor((treatAsUTC(endDate) - treatAsUTC(startDate)) / millisecondsPerDay);
}

// start date based on most recently scheduled recycling week
var demarcationdate = new Date("March 13, 2017 00:00:00"); // start date based on previously scheduled recycling week
    showTodaysDate = document.getElementById('todaysDate'),
    showNeighborhood = document.getElementById('neighborhood'),
    showFutureDate = document.getElementById('futureDate'),
    nextWeekBegins = document.getElementById('followingWeek'),
    monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
    today = new Date(),
    days = daysBetween(demarcationdate,today),
    daystill = 14 - days%14,
    rec = days%14==0,
    d = new Date();

// add remaining days to current date to get next recycling week start date
d.setDate(today.getDate() + daystill); 

// format dates to make them easy to read
var currentDate = (dayNames[today.getDay()] + ", " +  monthNames[today.getMonth()] + " " +  today.getDate() + ", " +  today.getFullYear());
var nextDate = (monthNames[d.getMonth()] + " " +  d.getDate());

// show current date, always on
showTodaysDate.innerHTML="Today is "+currentDate.toString()+", and "; 

// show start date of next recycling week and days remaining, always on
nextWeekBegins.innerHTML="The next recycling week begins " + dayNames[d.getDay()] + ", " + nextDate.toString() + " ("+daystill+" days from now)."



// Conditional display rules
var date1 = new Date(today); // today's date
var date2 = new Date(d); // day next recycling week starts
var timeDiff = Math.abs(date2.getTime() - date1.getTime()); // caluclate time between two dates
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)); // convert that time to days


if (diffDays <= 7) { 
// if (rec === true) { // ignore this, it's just to test 'showNeighborhood'
  // if it is not a recycling week, show the start date of the following recycling week
  showFutureDate.innerHTML="there is <strong>no recycling pickup</strong> scheduled this week."; 

} else {
  // if it is a recycling week, show scheduled neighborhood
  showNeighborhood.innerHTML = scheduleAllDays[scheduleCurrentDate.getDay()].neighborhood + " (excluding holidays). "; 
}
Mike Jandreau
  • 392
  • 3
  • 16
  • 1
    https://stackoverflow.com/questions/41230930/how-to-calculate-and-check-for-a-bi-weekly-date – imvain2 Mar 20 '19 at 20:11
  • If your app is going to run on a linux server like many applications do. You can use cron jobs: https://www.ostechnix.com/a-beginners-guide-to-cron-jobs/ – Matt Pengelly Mar 20 '19 at 20:11
  • I forgot to mention it's going to be a static site running on Netlify - I'll give imvain2's suggestion a try. Thanks! – Mike Jandreau Mar 21 '19 at 13:58
  • Mind taking a second look? I've updated my code and it seems to be working. – Mike Jandreau Mar 22 '19 at 18:43
  • Maybe you can get the week number of the year and if the result is divisible by two, it's time start the cycle anew. https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php – Iskandar Reza Mar 22 '19 at 21:45

0 Answers0