cipchk / ngx-countdown

Simple, easy and performance countdown for angular
https://cipchk.github.io/ngx-countdown/
MIT License
192 stars 57 forks source link

This is not working if leftTime is more than 24 hours #49

Closed kalimulhaq closed 4 years ago

kalimulhaq commented 5 years ago

This plugin is not working if leftTime is more than 24 hours e.g. leftTime: 60000 // 166 Hours count down is 22:40:00 // which is wrong

cipchk commented 5 years ago

@kalimulhaq Can u provide the ngx-countdown version and example code?

fuzails commented 5 years ago

@cipchk Please have a look at this StakBlitz this is on version 8.0.0

It is setup for 2 days i.e. 48 hours -> 2880 minutes -> 172800 seconds It should be counting down from 02d 00h 00m 00s but instead we get something like 02d 11h 57m 23s after initially showing 03d 12h 00m 00s

Compared to version 3.2.0 here StackBlitz

cipchk commented 5 years ago

@kalimulhaq @fuzails Yes, this is a problem.

In 3.x we are using manual parsing, which is why we need a weird $!h! template. And 8.x uses new Date, a standard date-time format.

A standard TimeStamp will be converted to Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time), which is why there is more 1d in dd.

So, if you hava dd requirement, you can subtract the extra 1days with formatDate.

Although it is very bad, but I can think of a solution at present.

fuzails commented 5 years ago

Will fork and have a look, it may just be some TZ tinkering required to resolve.

fuzails commented 5 years ago

@cipchk Ok, so the problem here has nothing to do with timezones, but rather the fact that you cannot use standard parsing with formatDate. This is basically a design flaw in version 8, and the only way to fix this is actually to go back to manual parsing.

formatDate is a date function so in a date fuction you cannot have more than 24 hours in a day so if the countdown timer is more than 24 hours formatDate will never work as the reality is that you are not trying to format a date at all but a count down. This is the same issue with days, format date will give you the day of the month from the unix epoch i.e. 01 Jan 1970.

To fix this you would have to go back to the manual parsing that was done before, come up with a complex interpreter to convert from a date to a countdown.

I would recommend going back to the previous implementation used in 3.2.0 and earlier.

if you really want to use format date you have to break up the format specified into its parts.

AS an example if the format is specified as HH:mm

you should get the HH and the mm separately then you should get the days less than 1 and multiply by 24

e.g. 172800 is actually the date Jan 3 1970 00:00:00 so we get 3 days and a time of 00 for hours and 00 for mins and so on so then we say 3 - 1 = 2 * 24 48 hours the you would display 48:00 as 48 +00: 00+00

now if you take 172799 is actually the date Jan 2 1970 23:59:59 so we get 2 days and a time of 23 for hours and 59 for mins and so on so then we say 2 - 1 = 1 * 24 24 hours then you would display 24 + 23 : 00 + 59 which is 47:59

as you see this may be already solved previously in version below 8, and so i would recommend going back to that approach.

Any reason you moved away from the manual parsing you had previously?

cipchk commented 4 years ago

@fuzails Sorry, forget this issues, i so busy.

you can try custom formatDate, like this:

const CountdownTimeUnits: Array<[string, number]> = [
  ['Y', 1000 * 60 * 60 * 24 * 365], // years
  ['M', 1000 * 60 * 60 * 24 * 30], // months
  ['D', 1000 * 60 * 60 * 24], // days
  ['H', 1000 * 60 * 60], // hours
  ['m', 1000 * 60], // minutes
  ['s', 1000], // seconds
  ['S', 1] // million seconds
];

formatDate?: CountdownFormatFn = ({ date, formatStr, timezone }) => {
  let duration = Number(date || 0);

  return CountdownTimeUnits.reduce((current, [name, unit]) => {
    if (current.indexOf(name) !== -1) {
      const v = Math.floor(duration / unit);
      duration -= v * unit;
      return current.replace(new RegExp(`${name}+`, 'g'), (match: string) => {
        return v.toString().padStart(match.length, '0');
      });
    }
    return current;
  }, formatStr);
};
jongbonga commented 4 years ago

is there a way to display more than 24hours like in the demo?

jahbolero commented 4 years ago

https://stackblitz.com/edit/ngx-countdown-setup-t82gh9 This doesn't work anymore on Angular ang ngx-countdown version 10^