Преобразовать строку даты UTC в число для значения конфигурации ngx-countdown leftTime

Я вызываю API C#, который возвращает следующие типы в мое приложение Angular.

export interface Auction {
      reservePrice: number        
      currentHighBid: number    
      auctionEnd: string   
      id: string         
}

Я создал компонент AuctionListComponent, который ngFor выводит на экран список аукционов, и в этот список я хочу добавить таймеры обратного отсчета. Поэтому я создал для этого еще один компонент под названием TimerComponent. Родительский компонент передает дочернему элементу дату в формате UTC. Дочернему компоненту таймера требуется тип числа для работы таймера обратного отсчета ngx. Я не профессионал в Angular, так что я упускаю что-то простое?

Я также просмотрел подобные вопросы и не помог мне. аналогичный вопрос

Ссылка на страницу nxg-countdown

(Родительский) AuctionListComponent.html

        <div class = "m-3" *ngFor = "let auction of auctions">

         <p class = "card-text">
              End Date: {{ auction.auctionEnd | date }}    
         </p>                   
                                                        
          <app-timer [childTimer] = "auction.auctionEnd"></app-timer>                             
            
        </div>

(Дочерний) TimerComponent.html

   <p>
    From the parent: <b>{{ childTimer | date : 'MM d, y, h:mm:ss a' }}</b>  
    UTC: <b>{{ childTimer }}</b>    
    </p>

    <p>ngx-countdown Counter</p>

    <countdown [config] = "config"> </countdown> 

ТаймерКомпонент.TS

 import { Component, Input } from '@angular/core';
 import { CountdownConfig, CountdownEvent } from 'ngx-countdown';

@Component({
  selector: 'app-timer',
  templateUrl: './timer.component.html',
  styleUrl: './timer.component.scss'
 })
export class TimerComponent {

   @Input() childTimer: string = ''; //This doesn't work because it's the wrong type
   @Input() childTimer: any; //This compiles and give an error
                             //ERROR Error: Unable to convert "Invalid Date" into a date

   config: CountdownConfig = { leftTime: this.childTimer, format: 'd:H:M:ss'};

}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Согласно документации ngx-countdown, параметр leftTime должен быть числом.

Поэтому, если вы преобразуете childTimer в число, создав экземпляр переменной конфигурации, он должен работать правильно.

Можете ли вы привести пример?

whisk 30.03.2024 22:15
Ответ принят как подходящий

ngx-countdown ожидает, что leftTime будет числом, обозначающим оставшиеся секунды. Итак, чтобы это заработало, вам нужно найти разницу между auctionEnd, которая является строкой UTC, и текущей датой, и преобразовать ее в секунды.

Вот как ваш компонент может это сделать:

export class TimerComponent {

 config: CountdownConfig = {
   leftTime: 0, 
   format: 'd:H:M:ss'
 };

 // Turn this into a setter so it updates the config if input changes
 // make sure you use ChangeDetectionStrategy.OnPush to avoid redundant updates
 // or change this as you wish
 @Input() set childTimer(utcDate: string) {
   this.config = {
     ...this.config,
     leftTime: this.calculateSecondsLeft(utcDate)
   };
 }

 private calculateSecondsLeft(utcDate: string): number {
   // Both `parse` and `now` return a timestamp
   const diff = Date.parse(utcDate) - Date.now();
   return diff / 1000;
 }

}

Обновлять

Я покопался в документации ngx-countdown и в конфигурации есть опция stopTime, которая делает ее еще проще, поскольку она принимает «время окончания» в качестве отметки времени, поэтому пример можно упростить до:

export class TimerComponent {

 config: CountdownConfig = {
   format: 'd:H:M:ss'
 };

 @Input() set childTimer(utcDate: string) {
   this.config = {
     ...this.config,
     stopTime: Date.parse(utcDate)
   };
 }

}

Что касается d в формате, показывающем 1, когда timeLeft > 24 часов. Кажется, библиотека использует форматирование даты, а данные больше похожи на Duration. Когда вычисляется diff, это дата относительно Jan 1 1970, а d — это «день месяца», поэтому отображается 1. Лучше объяснить здесь. Поскольку мы не можем вычесть 1 день из Jan 1 1970, нет простого решения, которое могло бы обрабатывать високосные дни и другие крайние случаи, связанные с датой.

Вот пример того, как вы можете добавить собственный форматтер через конфигурацию formatDate и intervalToDuration из библиотеки date-fns:

config: CountdownConfig = {
  formatDate: ({ date }) => {
    const { days, hours, minutes, seconds } = intervalToDuration({
      start: 0,
      end: date
    });
    return `${days ?? 0}:${hours ?? 0}:${minutes ?? 0}:${seconds ?? 0}`;
  },
};

Поэтому, когда я установил свой код на то, что у вас есть выше. В leftTime: this.calcSecLeft есть ошибка: Type 'number' is not assignable to type 'string'

whisk 30.03.2024 22:35

О, я оставил там неправильное начальное значение, и для него не было типа, попробуйте начать с 0 в качестве leftTime, я обновил ответ

Shlang 30.03.2024 22:38

оба ответа работают отлично! Мне просто интересно, почему, когда счетчик получает уже наступившую дату, он показывает: 1:0:1:00, а не 0:0:0:00. Есть идеи? предположим, что 1:0:1:00 — это 1 января 1970 года.

whisk 31.03.2024 00:44

@whisk библиотека не очень хорошо с этим справляется, к сожалению, я обновил ответ некоторой информацией, включая ссылку на соответствующую проблему и возможное решение.

Shlang 31.03.2024 13:11

Другие вопросы по теме