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
10 changes: 10 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules/
coverage/
dist/
.github/dependabot.yml
.github/FUNDING.yml
.github/workflows/sonarcloud.yml
.vscode/extensions.json
index.html
CONTRIBUTING.md
README.md
1 change: 1 addition & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"SonarSource.sonarlint-vscode"
]
}
}
24 changes: 12 additions & 12 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Website",
"file": "${workspaceFolder}/index.html"
}
]
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Website",
"file": "${workspaceFolder}/index.html"
}
]
}
11 changes: 7 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"sonarlint.connectedMode.project": {
"connectionId": "bellmano",
"projectKey": "bellmano_CountUpTimer"
}
"git.autofetch": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"sonarlint.connectedMode.project": {
"connectionId": "bellmano",
"projectKey": "bellmano_CountUpTimer"
}
}
16 changes: 11 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Make your changes and add or update tests
4. Run the tests: `npm test` or `npm run test:coverage`
5. Commit your changes: `git commit -m 'Add some feature'`
6. Push to the branch: `git push origin feature/your-feature`
7. Open a Pull Request
4. Format the code with [Prettier](https://prettier.io): `npm run format`
5. Run the tests: `npm test` or `npm run test:coverage`
6. Commit your changes: `git commit -m 'Add some feature'`
7. Push to the branch: `git push origin feature/your-feature`
8. Open a Pull Request

## Development Setup

1. Clone the repository: `git clone https://github.com/bellmano/CountUpTimer.git`
2. Install dependencies: `npm install`

## Code Style

- All code must be formatted with [Prettier](https://prettier.io) before it is committed or pushed. Run `npm run format` from the repository root.
- Write meaningful commit messages

## Testing

- Add or update unit tests for new features or bug fixes
- Ensure all tests pass before submitting a PR (`npm test` or `npm run test:coverage`)

## Issues

If you find a bug or have a feature request, please [open an issue](https://github.com/bellmano/CountUpTimer/issues).
If you find a bug or have a feature request, please [open an issue](https://github.com/bellmano/CountUpTimer/issues).
19 changes: 18 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,30 @@
"description": "Website that is counting up from the date/time specified in the code",
"scripts": {
"test": "jest",
"test:coverage": "jest --coverage"
"test:coverage": "jest --coverage",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"devDependencies": {
"jest": "^30.5.1",
"jest-environment-jsdom": "^30.5.1"
"jest-environment-jsdom": "^30.5.1",
"prettier": "^3.9.6"
},
"jest": {
"testEnvironment": "jsdom",
"collectCoverageFrom": [
"src/script.js"
],
"coverageDirectory": "coverage",
"coverageReporters": ["text", "lcov", "html"],
"coverageReporters": [
"text",
"lcov",
"html"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/tests/"
],
"transform": {}
}
}
}
39 changes: 26 additions & 13 deletions src/script.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function handleWindowOnload() {
// Set time and date where the timer should count from
countUpFromTime("Oct 21, 2001 17:00:00", 'countup1');
countUpFromTime("Oct 21, 2001 17:00:00", "countup1");
}

window.onload = handleWindowOnload;
Expand All @@ -19,7 +19,11 @@ function countUpFromTime(countFrom, id) {
return;
}

let years = 0, remainingDays = 0, hours = 0, minutes = 0, seconds = 0;
let years = 0,
remainingDays = 0,
hours = 0,
minutes = 0,
seconds = 0;
if (isValidDate) {
// Calculate timezone offsets for both dates
const countFromOffset = countFromDate.getTimezoneOffset() * 60000; // Offset in milliseconds
Expand All @@ -41,8 +45,13 @@ function countUpFromTime(countFrom, id) {

// Calculate years and remaining days, accounting for leap years and DST
remainingDays = totalDays;
for (let year = countFromDate.getFullYear(); year < now.getFullYear(); year++) {
const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
for (
let year = countFromDate.getFullYear();
year < now.getFullYear();
year++
) {
const isLeapYear =
(year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
const daysInYear = isLeapYear ? 366 : 365;
if (remainingDays >= daysInYear) {
years++;
Expand All @@ -59,22 +68,26 @@ function countUpFromTime(countFrom, id) {
remainingDays = exactDays;

hours = Math.floor((timeDifference % msInADay) / msInAnHour);
minutes = Math.floor(((timeDifference % msInADay) % msInAnHour) / (60 * 1000));
seconds = Math.floor((((timeDifference % msInADay) % msInAnHour) % (60 * 1000)) / 1000);
minutes = Math.floor(
((timeDifference % msInADay) % msInAnHour) / (60 * 1000),
);
seconds = Math.floor(
(((timeDifference % msInADay) % msInAnHour) % (60 * 1000)) / 1000,
);
}

idEl.getElementsByClassName('years')[0].innerHTML = years;
idEl.getElementsByClassName('days')[0].innerHTML = remainingDays;
idEl.getElementsByClassName('hours')[0].innerHTML = hours;
idEl.getElementsByClassName('minutes')[0].innerHTML = minutes;
idEl.getElementsByClassName('seconds')[0].innerHTML = seconds;
idEl.getElementsByClassName("years")[0].innerHTML = years;
idEl.getElementsByClassName("days")[0].innerHTML = remainingDays;
idEl.getElementsByClassName("hours")[0].innerHTML = hours;
idEl.getElementsByClassName("minutes")[0].innerHTML = minutes;
idEl.getElementsByClassName("seconds")[0].innerHTML = seconds;

clearTimeout(countUpFromTime.interval);
countUpFromTime.interval = setTimeout(countUpFromTime, 1000, countFrom, id);
}

// Export for Node.js/CommonJS (test environment)
/* istanbul ignore next */
if (typeof module !== 'undefined' && module.exports) {
if (typeof module !== "undefined" && module.exports) {
module.exports = { countUpFromTime, handleWindowOnload };
}
}
Loading