Edit in JSFiddle

const {
  dtFrags,
  dateAdd,
  dateSubtract,
} = DateAddFactory();
const [until0, until1, toNwYr, fromNwYr] = 
	[...document.querySelectorAll(`#timedUntil, #timedUntil2, #timedUntilNewYear, #timedFromLastNewYear`)];
const thisYearsNewYear = new Date(Date.UTC(new Date().getFullYear(), 11, 31));
const timer = TimerFactory();

time(thisYearsNewYear, toNwYr, timer);
time(dateSubtract(dtFrags.year, 1, thisYearsNewYear), fromNwYr, timer);
time(dateAdd(dtFrags.seconds, 5), until0, timer);
time(dateAdd(dtFrags.seconds, 10), until1, timer, true);

function time(date, reportField, timer, continueAfterPassed = false) {
  const isFuture = timer.toUTC(date) - timer.toUTC(new Date()) > 0;
  const stopGo = {
    stop: () => reportField.textContent = `${dateStr} passed`,
    go: () => time(date, reportField, timer),
  };
  const dateStr = new Date(date).toUTCString();
  const initStr = isFuture ?
    `<div>Time until ${dateStr}</div>` :
    `<div>From ${dateStr} until now lasted</div>`;
  const passed = isFuture && !continueAfterPassed ? stopGo.stop : isFuture ? stopGo.go : null;
  const writer = (difference, dtElements) => `
      ${initStr}${
        dtElements.day(difference.days)} ${dtElements.hour(difference.hours)} ${
        dtElements.minute(difference.minutes)} and ${dtElements.second(difference.seconds)}`;
  return timer.createAndStartTimer(reportField, date, writer, passed);
}

function TimerFactory() {
  const toUTC = someDate => Date.UTC(
    someDate.getUTCFullYear(), someDate.getUTCMonth(), someDate.getUTCDate(),
    someDate.getUTCHours(), someDate.getUTCMinutes(), someDate.getUTCSeconds());
  const logTo = (field, args) => field.innerHTML = args;
  const dtElements = dateTimeFragments(false);
  const writerFactory = (field, writer, value) =>
    diff => logTo(field, writer(diff, dtElements));
  const createTimer = (field, dateValue, writer, callback) =>
    counterFactory(dateValue, writerFactory(field, writer, dateValue), callback)

  return {
    createTimer,
    createAndStartTimer: (...args) => createTimer.call(null, ...args)(),
    toUTC,
  };

  function counterFactory(value, writer, callback) {
    const showTime = () => {
      const diffMS = value - new Date();
      const reIterate = () => {
        writer(dateDiffCalc(diffMS));
        setTimeout(showTime, 1000);
      };
      const exitCounter = () => callback instanceof Function && callback();
      return diffMS <= 0 && callback ? exitCounter() : reIterate();
    };
    return showTime;
  }

  function dateDiffCalc(milliseconds) {
    let secs = Math.floor(Math.abs(milliseconds) / 1000);
    let mins = Math.floor(secs / 60);
    let hours = Math.floor(mins / 60);
    let days = Math.floor(hours / 24);
    const millisecs = Math.floor(Math.abs(milliseconds)) % 1000;

    return {
      days: days,
      hours: hours % 24,
      minutes: mins % 60,
      seconds: secs % 60,
      milliSeconds: millisecs,
    };
  }

  function dateTimeFragments(doPad = true) {
    const pad = (val, width = 2) => !doPad ? val : val < 1 ? val : String(val).padStart(width, "0");
    const plural = (val, term) => `${term}${val !== 1 ? "s" : ""}`;
    const checkZero = (val, term, comma) => val < 1 ?
      "" : `<b>${pad(val)}</b> ${plural(val, term)}${comma ? ", " : ""}`;
    return {
      day: d => checkZero(d, "day", 1),
      hour: h => checkZero(h, "hour", 1),
      minute: m => `<b>${pad(m)}</b> ${plural(m, "minute")}`,
      second: s => `<b>${pad(s)}</b> ${plural(s, "second")}`
    };
  }
}

function DateAddFactory() {
  const dtFrags = {
    year: {
      set: "setFullYear",
      get: "getFullYear"
    },
    month: {
      set: "setMonth",
      get: "getMonth"
    },
    date: {
      set: "setDate",
      get: "getDate"
    },
    hours: {
      set: "setHours",
      get: "getHours"
    },
    minutes: {
      set: "setMinutes",
      get: "getMinutes"
    },
    seconds: {
      set: "setSeconds",
      get: "getSeconds"
    },
  };

  const dateAdd = (unit, value, date = new Date()) => {
    date = new Date(date);
    date[unit.set](date[unit.get]() + value);
    return date;
  };

  return {
    dtFrags,
    dateAdd,
    dateAddMulti: (values, date = new Date()) => {
      while (values.length) {
        const value = values.shift();
        date = dateAdd(value.unit, value.val, date);
      }
      return date;
    },
    dateSubtract: (unit, value, date) => dateAdd(unit, -value, date),
  };
}
<h3>
  Count down or up to a given <i>UTC</i>-date
</h3>
<div id="timedUntil" data-timer></div>
<p>
  <div>
    <b>Next timer continues after the time has passed</b>
  </div>
  <div id="timedUntil2" data-timer></div>
</p>
<h3>
  Time until next new year
</h3>
<div id="timedUntilNewYear" data-timer></div>

<h3>
  The current year now lasts
</h3>
<div id="timedFromLastNewYear" data-timer></div>
body {
  font: 16px/20px normal verdana, arial, helvetica;
  margin: 1.5em;
}

[data-timer] {
  margin-bottom: 0.7em;
}

[data-timer] div:first-child {
  font-style: italic;
  color: #AAA;
}

[data-timer] b {
  color: green;
}

h3 {
  margin-bottom: 0.3rem;
  min-width: 200px;
  text-decoration: underline;
}