我想创建一个显示两个日期之差的计时器

问题描述

我有一个应用程序,该应用程序显示使用两个日期“ 2020-09-05T18:03:00 + 05:30”以这种格式计算的剩余时间,一个是来自api的日期,另一个是当前日期我使用moment()。format()得到的时间,在获得时差之后,我想显示一个计时器,该计时器具有hour:minutes:seconds,它将每秒钟更新一次并减少时间,到目前为止,我所做的是/ p>

import { ReactComponent as Smiley } from 'Assets/Images/smiley.svg';
import { getAPatient } from '../api';
import moment from 'moment';

export default function WaitingRoom(props) {
    const { t } = useTranslation();
    const [timerComplete,setTimerComplete] = useState(false);

    const [language,setLanguage] = useState('en');

    const id = queryString.parse(props.location.search).id;

    const [modalStatus,setModalStatus] = useState({
        isModalOpen: false,content: null,});

    const [date,setDate] = useState(null);
    const [time,setTime] = useState(0);
    const [duration,setDuration] = useState(0);

    useEffect(() => {
        let interval = null;
        let duration = moment.duration(moment(date).diff(moment()));
        let value = duration.asSeconds();

        interval = setInterval(() => {
            setDuration(duration);
            setTime((time) => time - 1);
        },1000);
        return () => {
            clearInterval(interval);
        };
    },[time]);

    useEffect(() => {
        getAPatient(id)
            .then((info) => {
                if (info) {
                    console.log(moment(info.data.datetime).format(),moment().format(),"infooooo")
                    let duration = moment.duration(
                        moment(info.data.datetime).diff(moment())
                    );
                    let value = duration.asSeconds();
                    setTime(value.toFixed(0));
                    setDate(info.data.datetime);
                    setDuration(duration);
                } else {
                    console.log('error');
                }
            })
            .catch((err) => console.log(err));
    },[]);
    return !id ? (
        <BlueScreen>
            <Emoji>
                <Smiley />
            </Emoji>
            {language === 'en' ? (
                <Data>
                    <heading>{t('turnMessageheading')}</heading>
                    <Subheading>{t('turnMessageSubheading')}</Subheading>
                    <Subheading>{t('turnMessageSubheadingDoctor')}</Subheading>
                    <Button themeWhite>{t('commingMessage')}</Button>
                </Data>
            ) : (
                <Data>
                    <heading>{t('turnMessageChinese')}</heading>
                    <Subheading>{t('turnMessageSubheadingChinese')}</Subheading>
                    <Subheading>
                        {t('turnMessageSubheadingDoctorChinese')}
                    </Subheading>
                    <Button themeWhite>{t('commingMessageChinese')}</Button>
                </Data>
            )}
        </BlueScreen>
    ) : (
        <Box>
            <InfoModal
                modalStatus={modalStatus}
                setModalStatus={setModalStatus}
            />
            <Button themeBlue width={'100%'} textAlign={'left'}>
                {t('Virtual_waiting_room')}
            </Button>
            <Message>{t('waiting_message')}</Message>
            <Timer>
                <div>
                    {duration
                        ? moment
                              .utc(duration.as('milliseconds'))
                              .format('HH:mm:ss')
                        : 0}
                </div>
            </Timer>
            <WaitingImage>
                <Waiting />
            </WaitingImage>
            <Video>
                <iframe
                    src="https://www.youtube.com/embed/gaka1vqYFNs"
                    frameborder="0"
                    allow="autoplay; encrypted-media"
                    allowfullscreen
                    title="video"
                    width={'100%'}
                />
            </Video>
            <Footer>
                <p
                    onClick={() =>
                        setModalStatus({
                            isModalOpen: true,content: termOfService,})
                    }
                >
                    Terms Of Service
                </p>
                <p
                    onClick={() =>
                        setModalStatus({
                            isModalOpen: true,content: disclamer,})
                    }
                >
                    disclamer
                </p>
                <p
                    onClick={() =>
                        setModalStatus({
                            isModalOpen: true,content: privacyPolicy,})
                    }
                >
                    Privacy Policy
                </p>
            </Footer>
        </Box>
    );
}

但是我的计时器工作不正常,在此先感谢您的帮助

解决方法

  • 您只需要两个时刻日期,单个状态 setInterval
  • 计算日期差timeA - timeB / 1000秒。
  • 这成为状态的初始值。
  • 使用格式化程序功能显示倒数/计时器。
const getTimer = (sec) =>
        [sec / 3600,(sec / 60) % 60,sec % 60]
              .map((t) => Math.max(parseInt(t),0))
              .map((t) => (t < 10 ? "0" : "") + t)
              .join(":");

useEffect:

React.useEffect(() => {
        let interval = setInterval(() => setDuration((duration) => {
            if (duration == 1) clearInterval(interval);
            return duration - 1;
          }),1000);
        
        return () => { clearInterval(interval); };
    },[]);

在此处检查输出:https://jsfiddle.net/akqwzvx3/