{"id":13809029,"url":"https://github.com/rickar/cal","last_synced_at":"2026-03-09T15:31:38.192Z","repository":{"id":18302923,"uuid":"21478968","full_name":"rickar/cal","owner":"rickar","description":"Go (golang) calendar library for dealing with holidays and work days","archived":false,"fork":false,"pushed_at":"2025-12-03T01:08:30.000Z","size":333,"stargazers_count":397,"open_issues_count":14,"forks_count":129,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-12-06T01:46:30.280Z","etag":null,"topics":["business-calendar","calendar","calendar-library","go","golang","holidays","working-hours"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rickar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-07-03T22:34:08.000Z","updated_at":"2025-12-04T15:43:43.000Z","dependencies_parsed_at":"2023-01-11T20:28:36.731Z","dependency_job_id":"61315168-603d-4d74-bcb6-b2267960fdf4","html_url":"https://github.com/rickar/cal","commit_stats":{"total_commits":135,"total_committers":67,"mean_commits":2.014925373134328,"dds":0.8444444444444444,"last_synced_commit":"fdbdbbed2d8162963812c93988e902ea42b57cb4"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/rickar/cal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickar%2Fcal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickar%2Fcal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickar%2Fcal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickar%2Fcal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rickar","download_url":"https://codeload.github.com/rickar/cal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickar%2Fcal/sbom","scorecard":{"id":775716,"data":{"date":"2025-08-11","repo":{"name":"github.com/rickar/cal","commit":"ff261ab4580e000b4d4b3f97962c576072a68650"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/rickar/cal/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/rickar/cal/main.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T03:31:46.642Z","repository_id":18302923,"created_at":"2025-08-23T03:31:46.642Z","updated_at":"2025-08-23T03:31:46.642Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30301109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T14:33:48.460Z","status":"ssl_error","status_checked_at":"2026-03-09T14:33:48.027Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["business-calendar","calendar","calendar-library","go","golang","holidays","working-hours"],"created_at":"2024-08-04T01:01:58.696Z","updated_at":"2026-03-09T15:31:38.170Z","avatar_url":"https://github.com/rickar.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# cal/v2: Go (golang) calendar library for dealing with holidays and work days\n\nThis library augments the Go time package to provide easy handling of holidays\nand work days (business days).\n\nHoliday instances are calculated from either builtin or user-created functions\nto support exact days, floating days such as the 3rd Monday of the month, \nyearly offsets such as the 100th day of the year, or more complex rules such as \noffsets from Easter. Holidays may provide separate actual and observed dates \nfor cases where holidays are celebrated on an alternate day if they fall on a\nspecific day of the week (usually weekends).\n\nThe Calendar type provides the basic functionality for creating a yearly \ncalendar with holidays.\n\nBusinessCalendar adds additional functionality for calculating workdays and \nhours worked.\n\n# Differences from v1\nFor v2, much of the functionality of this library was rewritten to address\nshortcomings of the v1 releases. This version provides the following benefits\nover v1:\n* Holidays\n  * Observation rules are tied to individual holidays rather than a per-calendar \n  \tsetting\n  * Name, description, and observance type fields added\n  * Starting, ending, and exception year options\n  * Holiday definitions are separated into subpackages by ISO code (no longer \n    necessary to bundle all holidays in the final binary)\n* Calendar\n  * Separation of business specific functionality into BusinessCalendar\n  * Name and description fields added\n  * Support for time.Location matching to ease use of multiple Calendars\n* BusinessCalendar\n  * Full support for working hours and related calculations\n  * Work days and work start and end times can be provided by custom functions\n\n# Example\nHere is a simple usage example of a cron job that runs once per day:\n```go\npackage main\n\nimport (\n\t\"time\"\n\n\t\"github.com/rickar/cal/v2\"\n\t\"github.com/rickar/cal/v2/us\"\n)\n\nfunc main() {\n\tc := cal.NewBusinessCalendar()\n\tc.Name = \"Bigco, Inc.\"\n\tc.Description = \"Default company calendar\"\n\n\t// add holidays that the business observes\n\tc.AddHoliday(\n\t\tus.NewYear,\n\t\tus.MemorialDay,\n\t\tus.IndependenceDay,\n\t\tus.LaborDay,\n\t\tus.ThanksgivingDay,\n\t\tus.ChristmasDay,\n\t)\n\n\t// change the default of a Mon - Fri, 9am-5pm work week\n\tc.SetWorkday(time.Saturday, true)\n\tc.SetWorkHours(8*time.Hour, 18*time.Hour+30*time.Minute)\n\n\tt := time.Now()\n\n\t// run different batch processing jobs based on the day\n\n\tif c.IsWorkday(t) {\n\t\t// create daily activity reports\n\t}\n\n\tif cal.IsWeekend(t) {\n\t\t// validate employee time submissions\n\t}\n\n\tif c.WorkdaysRemain(t) == 10 {\n\t\t// 10 business days before the end of month\n\t\t// send account statements to customers\n\t}\n\n\tif c.WorkdaysRemain(t) == 0 {\n\t\t// last business day of the month\n\t\t// execute auto billing transfers\n\t}\n\n\t// determine the number of working hours left in the current month\n\tnextMonth := cal.DayStart(cal.MonthStart(t.AddDate(0, 1, 0)))\n\thoursLeft := c.WorkHoursInRange(t, nextMonth)\n\n\t// check if there are any tasks for this month that are in danger of missing their deadline\n\tpendingTasks := []struct{ pendingHours time.Duration }{{pendingHours: 32}} // assumed to be fetched from a DB or API\n\tfor _, task := range pendingTasks {\n\t\tif hoursLeft \u003c task.pendingHours {\n\t\t\t// send alert to management\n\t\t}\n\t}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickar%2Fcal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frickar%2Fcal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickar%2Fcal/lists"}