0

I'm a backend developer, who's trying hard to make a timer by comparing two different date formats. This part of the script is working great, but whenever I try to make recursive call, nothing is binding.

I almost tried everything, from passing it into a function, using the $interval, the setInterval, and on and on. The main reason is I cannot get the value of its loop, and binding into my DOM.

Here is some of my code. Here I set all variables for the countDown() function.

   $scope.timer.list        = {};
    $scope.timer.date       = new Date();
    $scope.timer.list.D     = '00';
    $scope.timer.list.M     = '00';
    $scope.timer.list.Y     = '00';
    $scope.timer.list.h     = '00';
    $scope.timer.list.m     = '00';
    $scope.timer.list.s     = '00';
    $scope.begin            = {};
    $scope.begin.date       = {};
    $scope.begin.timer      = {};
    $scope.counter = {
        show : false,
        text : '00:00'
    };
    setInterval(function() {
        $scope.obj = {
            show : $scope.countDown($scope.privateshowcase.begin_at).show,
            text : $scope.countDown($scope.privateshowcase.begin_at).text
        }
        $scope.counter = $scope.obj;
    }, 1000);

Then, here is the function:

$scope.countDown = function(begin) {
    $scope.timer.date       = new Date();

    $scope.timer.list.D = $filter('date')($scope.timer.date, 'dd');
    $scope.timer.list.M = $filter('date')($scope.timer.date, 'MM');
    $scope.timer.list.Y = $filter('date')($scope.timer.date, 'yyyy');
    $scope.timer.list.h = $filter('date')($scope.timer.date, 'HH');
    $scope.timer.list.m = $filter('date')($scope.timer.date, 'mm');
    $scope.timer.list.s = $filter('date')($scope.timer.date, 'ss');

    $scope.begin.full = begin.split(" ");
    $scope.begin.date = $scope.begin.full[0].split("-");
    $scope.begin.timer = $scope.begin.full[1].split(":");

    $scope.begin.D = $scope.begin.date[2];
    $scope.begin.M = $scope.begin.date[1];
    $scope.begin.Y = $scope.begin.date[0];
    $scope.begin.h = $scope.begin.timer[0];
    $scope.begin.m = $scope.begin.timer[1];
    $scope.begin.s = $scope.begin.timer[2];

    if($scope.timer.list.Y == $scope.begin.Y) {
        if($scope.timer.list.M == $scope.begin.M) {
            if($scope.timer.list.D == $scope.begin.D) {
                $scope.counter.diff_h = $scope.timer.list.h - $scope.begin.h;
                if($scope.counter.diff_h == 0 || $scope.counter.diff_h == -1) {
                    if($scope.counter.diff_h == 0) {
                        if($scope.timer.list.m > $scope.begin.m) {
                            $scope.counter.show = false;
                            $scope.counter.text = false;
                        } else if ($scope.timer.list.m <= $scope.begin.m) {
                            $scope.counter.show = true;
                            $scope.counter.diff_m = $scope.begin.m - $scope.timer.list.m;
                            if($scope.counter.diff_m <= 30) {
                                $scope.counter.diff_s = 60 - $scope.timer.list.s;
                                if($scope.counter.diff_s == 60) {
                                    $scope.counter.s = "00";
                                    $scope.counter.diff_m_f = $scope.counter.diff_m + 1;
                                } else if($scope.counter.diff_s >= 1 && $scope.counter.diff_s <= 9) {
                                    $scope.counter.s = "0" + $scope.counter.diff_s;
                                    $scope.counter.diff_m_f = $scope.counter.diff_m;
                                } else {
                                    $scope.counter.s = $scope.counter.diff_s;
                                    $scope.counter.diff_m_f = $scope.counter.diff_m;
                                }
                                if($scope.counter.diff_m_f >= 1 && $scope.counter.diff_m_f <= 9) {
                                    $scope.counter.m = "0" + $scope.counter.diff_m_f;
                                } else {
                                    $scope.counter.m = $scope.counter.diff_m_f;
                                }
                            }
                            $scope.counter.text = $scope.counter.m + ":" +$scope.counter.s;

                        } else {
                            $scope.counter.show = false;
                            $scope.counter.text = false;
                        }
                    } else if ($scope.counter.diff_h == -1) {

                        $scope.counter.diff_timer = $scope.timer.m - 60;
                        $scope.counter.diff_m =  $scope.begin.m - $scope.counter.diff_timer;
                        if($scope.counter.diff_m > 30) {
                            $scope.counter.show = false;
                            $scope.counter.text = false; 
                        } else if($scope.counter.diff_m <= 30) {
                            $scope.counter.show = true;
                            $scope.counter.diff_timer_s = $scope.timer.s - 60;
                            if($scope.counter.diff_timer_s == 60) {
                                $scope.counter.s = "00";
                                $scope.counter.m = $scope.counter.diff_m + 1;
                            } else if($scope.counter.s >= 1 && $scope.counter.s <= 9) {
                                $scope.counter.s = "0" + $scope.counter.diff_timer_s;
                                $scope.counter.m = $scope.counter.diff_m;
                            } else {
                                $scope.counter.s = $scope.counter.diff_timer_s;
                                $scope.counter.m = $scope.counter.diff_m;
                            }
                            $scope.counter.text = $scope.counter.m + ":" +$scope.counter.s;
                        } else {
                            $scope.counter.show = false;
                            $scope.counter.text = false;
                        }
                    } else {
                        $scope.counter.show = false;
                        $scope.counter.text = false;
                    }
                } else {
                    $scope.counter.show = false;
                    $scope.counter.text = false;
                }
            } else {
                $scope.counter.show = false;
                $scope.counter.text = false;
            }
        } else {
                $scope.counter.show = false;
                $scope.counter.text = false;
        }
    } else {
        $scope.counter.show = false;
        $scope.counter.text = false;
    }
    return $scope.counter = {
        show : $scope.counter.show,
        text : $scope.counter.text
    };
}

'begin' is : 'YYYY/MM/DAY HH:MM:SS'

Maybe my way of thinking is not the good one, but at list I have a very functional timer, which replace every 1 to 9 into 01 to 09, convert the 60 into 00, can compare 2 different hours.

5
  • You say you're "trying hard to make a timer by comparing two different date formats." I don't quite understand, and your code isn't easy for me to grok. Can you explain a bit more about what your goal is? Commented Sep 12, 2017 at 14:19
  • It's a countDown, so the script is recovering a date from an API (begin: "'YYYY/MM/DAY HH:MM:SS') and then is compared to the current date return by the browser. Commented Sep 12, 2017 at 14:41
  • So you want it to display something like 10:00:00 remaining, and then one second later update to 9:59:59 remaining, and so on? Also, what format is begin in? Is it an integer of UTC seconds? Is it a human readable string? Commented Sep 12, 2017 at 14:43
  • Basically I'm returning 2 variables counter.show, and counter.text. Show is a boolean, it triggers if the countDown div is showing or not. Text is the countDown() result which is something like '01:19' MM:SS. The function is working, and is doing nothing more than some basics math to get the correct value to display. Commented Sep 12, 2017 at 14:44
  • Exactly, and Begin is a basic NOW() SQL return, so it's a string like this 'YYYY/MM/DAY HH:MM:SS' Commented Sep 12, 2017 at 14:46

1 Answer 1

2

I think you are over complicating things a little bit. I came up with a simple countDown component made in angularjs 1.6.0 (it can be done with directives for angularjs older versions as well) that compares an input Date with the now Date.

You can play around with the input and change dates to see changes happen on the component, as long as you don't break the date format.

Note on dates: simple way to compare dates:

var date0 = new Date("2017-09-12T14:45:00.640Z");
var date1 = new Date("2017-09-13T14:45:00.640Z");

var dateDiff = new Date(date1.getTime() - date0.getTime());
// "1970-01-02T00:00:00.000Z"

Although dateDiff looks weird, it's basically one day from the zero date 1970-01-01T00:00:00.000Z.

Given that, you just let angularjs do the magic (or maybe trick).

{{ dateDiff | date:"d \'days\' hh:mm:ss" }}

Besides, if you don't want to work with dates in the natural form of javascript, you can use angularjs-moment which provide you date and time utility from momentjs regardless of javascript dates pitfalls.

Here is the working code:

angular
  .module('app', [])
  .run(function($rootScope) {
    $rootScope.countDownToDate = new Date().addDays(2);
  })
  .component('countDown', {
    template: '{{ $ctrl.timer | date:"d \'days\' hh:mm:ss" }}',
    bindings: {
      to: '<'
    },
    controller: function CountDownCtrl($interval) {
      var $this = this;

      this.$onInit = function() {
        $interval($this.setTime, 1000);
      };

      $this.setTime = function() {
        $this.timer = new Date(new Date($this.to).getTime() - new Date().getTime());
      }
    }
  });

// bootstrap the app
angular.element(function() {
  angular.bootstrap(document, ['app']);
});

// extension to add days on date
Date.prototype.addDays = function(days) {
  var dat = new Date(this.valueOf());
  dat.setDate(dat.getDate() + days);
  return dat;
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<div>
  <center>
    <h1>
      <count-down to="countDownToDate" />
    </h1>
    <label for="countDownToDate">To Date</label>
    <input type="datetime" name="countDownToDate" ng-model="countDownToDate">
  </center>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

You are right, I'm maybe over complicating, but I wanted to start the count down 30minutes before the beginning date, and things came out this way. I cannot change my date format, because it's an API response, and the owner dont want to change it.
It's ok, you can add minutes instead of days. Also, about the date format, you just have to parse it into a Date object like new Date(2017,8,12,12, 11 + 30min, 00). Again, the component is dumb, it doesn't have to know about how you reach the date, just pass the date as an attribute (a.k.a., binding) and it's done.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.