Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 13 additions & 45 deletions src/useStopwatch.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,22 @@
import { useState, useEffect, useRef } from 'react';
import { Time } from './utils';

export default function useStopwatch(settings) {
const { autoStart } = settings || {};

const [seconds, setSeconds] = useState(0);
const [minutes, setMinutes] = useState(0);
const [hours, setHours] = useState(0);
const [days, setDays] = useState(0);
const intervalRef = useRef();

function addDay() {
setDays((prevDays) => (prevDays + 1));
}

function addHour() {
setHours((prevHours) => {
if (prevHours === 23) {
addDay();
return 0;
}
return prevHours + 1;
});
}

function addMinute() {
setMinutes((prevMinutes) => {
if (prevMinutes === 59) {
addHour();
return 0;
}
return prevMinutes + 1;
});
}

function addSecond() {
setSeconds((prevSeconds) => {
if (prevSeconds === 59) {
addMinute();
return 0;
}
return prevSeconds + 1;
});
function clearIntervalRef() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
}

function start() {
if (!intervalRef.current) {
intervalRef.current = setInterval(() => addSecond(), 1000);
intervalRef.current = setInterval(() => setSeconds((prevSeconds) => (prevSeconds + 1)), 1000);
}
}

Expand All @@ -57,25 +28,22 @@ export default function useStopwatch(settings) {
}

function reset() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
clearIntervalRef();
setSeconds(0);
setMinutes(0);
setHours(0);
setDays(0);
if (autoStart) {
start();
}
}

// didMount effect
useEffect(() => {
if (autoStart) {
start();
}
return reset;
return clearIntervalRef;
}, []);

return {
seconds, minutes, hours, days, start, pause, reset,
...Time.getTimeFromSeconds(seconds), start, pause, reset,
};
}
48 changes: 9 additions & 39 deletions src/useTime.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,33 @@
import { useState, useEffect, useRef } from 'react';
import { Time } from './utils';

export default function useTime(settings) {
const { format } = settings || {};

const [seconds, setSeconds] = useState(0);
const [minutes, setMinutes] = useState(0);
const [hours, setHours] = useState(0);
const [ampm, setAmPm] = useState('');
const [seconds, setSeconds] = useState(Time.getSecondsFromTimeNow());
const intervalRef = useRef();

function formatHours(hoursValue) {
if (format === '12-hour') {
const ampmValue = hoursValue >= 12 ? 'pm' : 'am';
let formattedHours = hoursValue % 12;
formattedHours = formattedHours || 12;
return { hoursValue: formattedHours, ampmValue };
function clearIntervalRef() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
return { hoursValue, ampmValue: '' };
}

function setCurrentTime() {
const now = new Date();
const secondsValue = now.getSeconds();
const minutesValue = now.getMinutes();
const { hoursValue, ampmValue } = formatHours(now.getHours());

setSeconds(secondsValue);
setMinutes(minutesValue);
setHours(hoursValue);
setAmPm(ampmValue);
}


function start() {
if (!intervalRef.current) {
setCurrentTime();
intervalRef.current = setInterval(() => setCurrentTime(), 1000);
}
}

function reset() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
intervalRef.current = setInterval(() => setSeconds(Time.getSecondsFromTimeNow()), 1000);
}
setSeconds(0);
setMinutes(0);
setHours(0);
setAmPm('');
}

// didMount effect
useEffect(() => {
start();
return reset;
return clearIntervalRef;
}, []);


return {
seconds, minutes, hours, ampm,
...Time.getFormattedTimeFromSeconds(seconds, format),
};
}
141 changes: 30 additions & 111 deletions src/useTimer.js
Original file line number Diff line number Diff line change
@@ -1,148 +1,67 @@
import { useState, useEffect, useRef } from 'react';


function isValidExpiryTimestamp(expiryTimestamp) {
const isValid = (new Date(expiryTimestamp)).getTime() > 0;
if (!isValid) {
console.warn('react-timer-hook: { useTimer } Invalid expiryTimestamp settings', expiryTimestamp);
}
return isValid;
}

function isValidOnExpire(onExpire) {
const isValid = onExpire && typeof onExpire === 'function';
if (onExpire && !isValid) {
console.warn('react-timer-hook: { useTimer } Invalid onExpire settings function', onExpire);
}
return isValid;
}
import { Time, Validate } from './utils';

export default function useTimer(settings) {
const { expiryTimestamp: expiry, onExpire } = settings || {};
const [expiryTimestamp, setExpiryTimestamp] = useState(expiry);

const [seconds, setSeconds] = useState(0);
const [minutes, setMinutes] = useState(0);
const [hours, setHours] = useState(0);
const [days, setDays] = useState(0);
const [seconds, setSeconds] = useState(Time.getSecondsFromExpiry(expiryTimestamp));
const intervalRef = useRef();

function reset() {
function clearIntervalRef() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
setSeconds(0);
setMinutes(0);
setHours(0);
setDays(0);
}

function subtractDay() {
setDays((prevDays) => {
if (prevDays > 0) {
return prevDays - 1;
}
reset();
isValidOnExpire(onExpire) && onExpire();
return 0;
});
}

function subtractHour() {
setHours((prevHours) => {
if (prevHours === 0) {
subtractDay();
return 23;
}

if (prevHours > 0) {
return prevHours - 1;
}
return 0;
});
}

function subtractMinute() {
setMinutes((prevMinutes) => {
if (prevMinutes === 0) {
subtractHour();
return 59;
}

if (prevMinutes > 0) {
return prevMinutes - 1;
}
return 0;
});
}

function subtractSecond() {
setSeconds((prevSeconds) => {
if (prevSeconds === 0) {
subtractMinute();
return 59;
}

if (prevSeconds > 0) {
return prevSeconds - 1;
}
return 0;
});
}

// Timer expiry date calculation
function calculateExpiryDate() {
const now = new Date().getTime();
const distance = expiryTimestamp - now;
const daysValue = Math.floor(distance / (1000 * 60 * 60 * 24));
const hoursValue = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutesValue = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const secondsValue = Math.floor((distance % (1000 * 60)) / 1000);
if (secondsValue < 0) {
reset();
isValidOnExpire(onExpire) && onExpire();
} else {
setSeconds(secondsValue);
setMinutes(minutesValue);
setHours(hoursValue);
setDays(daysValue);
}
function handleExpire() {
clearIntervalRef();
Validate.onExpire(onExpire) && onExpire();
}

function start() {
if (isValidExpiryTimestamp(expiryTimestamp) && !intervalRef.current) {
calculateExpiryDate();
intervalRef.current = setInterval(() => calculateExpiryDate(), 1000);
if (!intervalRef.current) {
intervalRef.current = setInterval(() => {
const secondsValue = Time.getSecondsFromExpiry(expiryTimestamp);
if (secondsValue <= 0) {
handleExpire();
}
setSeconds(secondsValue);
}, 1000);
}
}

function pause() {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
clearIntervalRef();
}

function resume() {
if (isValidExpiryTimestamp(expiryTimestamp) && !intervalRef.current) {
intervalRef.current = setInterval(() => subtractSecond(), 1000);
if (!intervalRef.current) {
intervalRef.current = setInterval(() => setSeconds((prevSeconds) => {
const secondsValue = prevSeconds - 1;
if (secondsValue <= 0) {
handleExpire();
}
return secondsValue;
}), 1000);
}
}

function restart(newExpiryTimestamp) {
reset();
clearIntervalRef();
setExpiryTimestamp(newExpiryTimestamp);
}

// didMount effect
useEffect(() => {
start();
return reset;
if (Validate.expiryTimestamp(expiryTimestamp)) {
setSeconds(Time.getSecondsFromExpiry(expiryTimestamp));
start();
}
return clearIntervalRef;
}, [expiryTimestamp]);


return {
seconds, minutes, hours, days, start, pause, resume, restart,
...Time.getTimeFromSeconds(seconds), start, pause, resume, restart,
};
}
49 changes: 49 additions & 0 deletions src/utils/Time.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
export default class Time {
static getTimeFromSeconds(totalSeconds) {
const days = Math.floor(totalSeconds / (60 * 60 * 24));
const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60));
const minutes = Math.floor((totalSeconds % (60 * 60)) / 60);
const seconds = Math.floor(totalSeconds % 60);

return {
seconds,
minutes,
hours,
days,
};
}

static getSecondsFromExpiry(expiry) {
const now = new Date().getTime();
const milliSecondsDistance = expiry - now;
if (milliSecondsDistance > 0) {
return Math.floor(milliSecondsDistance / 1000);
}
return 0;
}

static getSecondsFromTimeNow() {
const now = new Date();
const currentTimestamp = now.getTime();
const offset = (now.getTimezoneOffset() * 60);
return (currentTimestamp / 1000) - offset;
}

static getFormattedTimeFromSeconds(totalSeconds, format) {
const { seconds: secondsValue, minutes, hours } = Time.getTimeFromSeconds(totalSeconds);
let ampm = '';
let hoursValue = hours;

if (format === '12-hour') {
ampm = hours >= 12 ? 'pm' : 'am';
hoursValue = hours % 12;
}

return {
seconds: secondsValue,
minutes,
hours: hoursValue,
ampm,
};
}
}
Loading