{"id":24302773,"url":"https://github.com/taigrr/most-specific-period","last_synced_at":"2026-06-08T05:31:06.728Z","repository":{"id":102066981,"uuid":"464660516","full_name":"taigrr/most-specific-period","owner":"taigrr","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-05T22:30:23.000Z","size":57,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-06T00:33:55.653Z","etag":null,"topics":["go","golang","hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"0bsd","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taigrr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"taigrr","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2022-02-28T22:10:54.000Z","updated_at":"2026-05-05T22:30:27.000Z","dependencies_parsed_at":"2023-04-15T13:31:35.287Z","dependency_job_id":null,"html_url":"https://github.com/taigrr/most-specific-period","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/taigrr/most-specific-period","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fmost-specific-period","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fmost-specific-period/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fmost-specific-period/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fmost-specific-period/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taigrr","download_url":"https://codeload.github.com/taigrr/most-specific-period/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taigrr%2Fmost-specific-period/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34050225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["go","golang","hacktoberfest"],"created_at":"2025-01-17T00:19:19.286Z","updated_at":"2026-06-08T05:31:06.723Z","avatar_url":"https://github.com/taigrr.png","language":"Go","funding_links":["https://github.com/sponsors/taigrr"],"categories":[],"sub_categories":[],"readme":"# Most Specific Period\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/taigrr/most-specific-period.svg)](https://pkg.go.dev/github.com/taigrr/most-specific-period)\n[![Go Report Card](https://goreportcard.com/badge/github.com/taigrr/most-specific-period)](https://goreportcard.com/report/github.com/taigrr/most-specific-period)\n\nA Go library for selecting the narrowest time period containing a given\ntimestamp from a set of potentially overlapping periods.\n\n## Installation\n\n```bash\ngo get github.com/taigrr/most-specific-period\n```\n\n## What is a Most Specific Period?\n\nGiven overlapping time periods, the MSP algorithm picks the most precise one:\n\n- Given a single valid period containing the timestamp, that period is chosen.\n- Given two overlapping periods of different lengths, the shorter one wins.\n- Given two periods of equal length, the one that started more recently wins.\n- Given two periods with the same duration and start time, the lexicographically\n  last identifier wins (e.g. \"B\" over \"A\").\n- Periods that haven't started yet or have already ended are ignored.\n\n## Usage\n\nImplement the `Period` interface or use the built-in `TimeWindow`:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/taigrr/most-specific-period/msp\"\n)\n\nfunc main() {\n\tnow := time.Now()\n\n\tperiods := []msp.Period{\n\t\tmsp.TimeWindow{\n\t\t\tStartTime:  now.Add(-24 * time.Hour),\n\t\t\tEndTime:    now.Add(24 * time.Hour),\n\t\t\tIdentifier: \"this-week\",\n\t\t},\n\t\tmsp.TimeWindow{\n\t\t\tStartTime:  now.Add(-1 * time.Hour),\n\t\t\tEndTime:    now.Add(1 * time.Hour),\n\t\t\tIdentifier: \"this-morning\",\n\t\t},\n\t}\n\n\tid, err := msp.MostSpecificPeriod(now, periods...)\n\tif err != nil {\n\t\tfmt.Println(\"No matching period\")\n\t\treturn\n\t}\n\tfmt.Printf(\"MSP: %s\\n\", id) // \"this-morning\"\n}\n```\n\n### Period Interface\n\n```go\ntype Period interface {\n\tGetStartTime()  time.Time // Inclusive start time\n\tGetEndTime()    time.Time // Exclusive end time\n\tGetIdentifier() string\n}\n```\n\n### Additional Functions\n\n- `GenerateTimeline(periods...)` — Flatten overlapping periods into a\n  non-overlapping timeline.\n- `GetChangeOvers(periods...)` — Get timestamps where the MSP changes.\n- `GetNextChangeOver(t, periods...)` — Get the next changeover after time `t`.\n- `FlattenPeriods(periods...)` — Get ordered identifiers at each changeover.\n- `ValidTimePeriods(ts, periods...)` — Filter periods valid at timestamp `ts`.\n- `GetDuration(start, end)` — Calculate duration between two times.\n\n## CLI\n\nA demo CLI is included. It reads periods from stdin (one per three lines:\nidentifier, start time, end time in RFC 3339) and displays the timeline\nand MSP.\n\n```bash\ngo run . -d 2024-06-15T12:00:00Z \u003c\u003cEOF\nsummer\n2024-06-01T00:00:00Z\n2024-09-01T00:00:00Z\njune\n2024-06-01T00:00:00Z\n2024-07-01T00:00:00Z\nEOF\n```\n\n## License\n\n0BSD — See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaigrr%2Fmost-specific-period","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaigrr%2Fmost-specific-period","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaigrr%2Fmost-specific-period/lists"}