{"id":41583756,"url":"https://github.com/borutainfo/timebase","last_synced_at":"2026-01-24T08:48:28.918Z","repository":{"id":56951188,"uuid":"330438713","full_name":"borutainfo/timebase","owner":"borutainfo","description":"Flat file database for storage any data as events in timeline and finding it for a given timestamp.","archived":false,"fork":false,"pushed_at":"2021-01-30T17:45:44.000Z","size":30,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-21T04:52:58.707Z","etag":null,"topics":["binary-search","database","events","file-database","flat-database","php","timeline","timestamp"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/borutainfo.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}},"created_at":"2021-01-17T16:46:49.000Z","updated_at":"2023-02-11T19:18:17.000Z","dependencies_parsed_at":"2022-08-21T03:40:22.935Z","dependency_job_id":null,"html_url":"https://github.com/borutainfo/timebase","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/borutainfo/timebase","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borutainfo%2Ftimebase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borutainfo%2Ftimebase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borutainfo%2Ftimebase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borutainfo%2Ftimebase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/borutainfo","download_url":"https://codeload.github.com/borutainfo/timebase/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borutainfo%2Ftimebase/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28721222,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T08:27:05.734Z","status":"ssl_error","status_checked_at":"2026-01-24T08:27:01.197Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["binary-search","database","events","file-database","flat-database","php","timeline","timestamp"],"created_at":"2026-01-24T08:48:28.806Z","updated_at":"2026-01-24T08:48:28.876Z","avatar_url":"https://github.com/borutainfo.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TimeBase\n![Tests Status](https://badgen.net/badge/tests/success/green)\n\nFlat file database for storage any data as events in timeline and finding it for a given timestamp.\n\n### Table of contents\n1. [Description](#description)\n2. [Requirements](#requirements)\n3. [Installation](#installation)\n4. [Usage](#usage)\n    1. [Quick introduction](#quick-introduction)\n    2. [Details](#details)\n       1. [Extra logger in constructor](#extra-logger-in-constructor)\n       2. [Data types](#data-types)\n       3. [Setting the storage namespace](#setting-the-storage-namespace) \n       4. [Inserting data for specific timestamp](#inserting-data-for-specific-timestamp)\n       5. [Searching data for specific timestamp](#searching-data-for-specific-timestamp)\n       6. [Getting multiple records with the same timestamp](#getting-multiple-records-with-the-same-timestamp)\n       7. [Searching strategies](#searching-strategies)\n5. [Tests](#tests)\n\n## Description\n\nThe data are stored in files, with the possibility of using multi-level namespaces - in this case, the files are stored in subdirectories. Each day is stored in a separate file named `YYYY-MM-DD.tb`.\n\nThe data records are searched using a binary search algorithm, so it's quick and doesn't require loading the entire file into memory. Each record is one line in file, in format `{timestamp}/{data}` (`data` is result of `base64_encode(json_encode(...))`). The records are sorted, and you can add multiple records for one timestamp - they are saved and returned in the order they were added.\n\nThere are many use cases for such a database, e.g. storing stock exchange data (volumes, price values etc.) for trading strategy backtesting.\n\n## Requirements\n\nPackage requires PHP \u003e= 7.3 and ext-json installed.\n\n## Installation\n\nInstall the library using Composer. Please read\nthe [Composer Documentation](https://getcomposer.org/doc/01-basic-usage.md) if you are unfamiliar with Composer or\ndependency managers in general.\n\n```shell\ncomposer require boruta/timebase\n```\n\n## Usage\n\n### Quick introduction\n\nCreating database instance. First constructor argument is a path where to store database files.\n\n```php\n$timebase = new Boruta\\Timebase\\Timebase(__DIR__ . '/database/');\n```\n\nInserting data (for current timestamp) :\n\n```php\n$timebase-\u003einsert()-\u003eset('test')-\u003eexecute();\n```\n\nGetting last inserted data (last record):\n\n```php\n$result = $timebase-\u003esearch()-\u003eexecute();\n```\n\nYou will get array as result, with keys `timestamp` and `value`:\n```php\narray(2) {\n  [\"timestamp\"]=\u003e\n  int(1612022907)\n  [\"value\"]=\u003e\n  string(4) \"test\"\n}\n```\n\n### Details \n\n#### Extra logger in constructor\n\nYou can optionally give the second argument which is a logger object, compatible with `Psr\\Log\\LoggerInterface`. The application append logs only in case of errors.\n```php\n$timebase = new Boruta\\Timebase\\Timebase(__DIR__ . '/database/', $logger);\n```\n\n#### Data types\n\nThe data can be of any native type, e.g. `int`, `string`, `array`. When searching for data, they will be of the same type.\n```php\n$timebase-\u003einsert()\n    -\u003eset(123) // or -\u003eset('test') or -\u003eset(['test' =\u003e 123]) etc.\n    -\u003eexecute();\n```\n\n#### Setting the storage namespace\n\nYou can store your data in different storages on many levels. Please use the method `-\u003estorage(array $storage)` to set this.\n\nExamples of inserting data into specific storage:\n```php\n$timebase-\u003einsert()\n    -\u003estorage(['test']) // storage path: __DIR__ . '/database/test/'\n    -\u003eset('test')\n    -\u003eexecute();\n```\n\n```php\n$timebase-\u003einsert()\n    -\u003estorage(['level0', 'level1']) // storage path: __DIR__ . '/database/level0/level1/'\n    -\u003eset('test')\n    -\u003eexecute();\n```\n\nExamples of reading data from specific storage:\n```php\n$result = $timebase-\u003esearch()\n    -\u003estorage(['test']) // storage path: __DIR__ . '/database/test/'\n    -\u003eexecute();\n```\n\n```php\n$result = $timebase-\u003esearch()\n    -\u003estorage(['level0', 'level1']) // storage path: __DIR__ . '/database/level0/level1/'\n    -\u003eexecute();\n```\n\n#### Inserting data for specific timestamp\n\nTo add data for a given timestamp (not the current) use the method `-\u003etimestamp(int $timestamp)`. Example:\n```php\n$timebase-\u003einsert()\n    -\u003etimestamp(1612022907)\n    -\u003eset('test')\n    -\u003eexecute();\n```\n\n#### Searching data for specific timestamp\n\nTo find a record for a specific timestamp use the method `-\u003etimestamp(int $timestamp)` during search query:\n\n```php\n$result = $timebase-\u003esearch()\n    -\u003etimestamp(1612022907)\n    -\u003eexecute();\n```\nIn the default strategy, you will get one record that is closest to the timestamp you entered.\n\n#### Getting multiple records with the same timestamp\nIf you have more than one record with the same timestamp you can retrieve them using the `-\u003eall()` method. \n```php\n$result = $timebase-\u003esearch()\n    -\u003etimestamp(1612022907)\n    -\u003eall()\n    -\u003eexecute();\n```\nIn the result array there will be an additional key `all` containing all records for given timestamp, in the order in which they were added:\n```php\narray(3) {\n  [\"timestamp\"]=\u003e\n  int(1612012606)\n  [\"value\"]=\u003e\n  string(4) \"test\"\n  [\"all\"]=\u003e\n  array(2) {\n    [0]=\u003e\n    string(4) \"test\"\n    [1]=\u003e\n    string(4) \"test\"\n  }\n}\n```\n\n\n#### Searching strategies\n\n**Nearest** (default)\n\nThe default strategy returns the record with the nearest timestamp to the given one. Usage (is not necessary as it is the default):\n```php\n$result = $timebase-\u003esearch()\n    -\u003estrategy(\\Boruta\\Timebase\\Common\\Constant\\SearchStrategyConstant::NEAREST)\n    -\u003etimestamp(1612022907)\n    -\u003eexecute();\n```\nIf the time distance is the same for two records, you will get the earlier one. \n\n**Exact**\n\nIf there is no record for the timestamp you provided, you will get `null` value. There must be a record in the database with exactly the same timestamp.\n```php\n$result = $timebase-\u003esearch()\n    -\u003estrategy(\\Boruta\\Timebase\\Common\\Constant\\SearchStrategyConstant::EXACT)\n    -\u003etimestamp(1612022907)\n    -\u003eexecute();\n```\n\n**Earlier**\n\nIf there is no record for the timestamp you entered, you will get the closest one before that timestamp or `null`.\n```php\n$result = $timebase-\u003esearch()\n    -\u003estrategy(\\Boruta\\Timebase\\Common\\Constant\\SearchStrategyConstant::EARLIER)\n    -\u003etimestamp(1612022907)\n    -\u003eexecute();\n```\n\n**Later**\n\nIf there is no record for the timestamp you entered, you will get the closest one after that timestamp or `null`.\n```php\n$result = $timebase-\u003esearch()\n    -\u003estrategy(\\Boruta\\Timebase\\Common\\Constant\\SearchStrategyConstant::LATER)\n    -\u003etimestamp(1612022907)\n    -\u003eexecute();\n```\n\n## Tests\nTo run the tests in the package, execute the following command:\n```shell\nvendor/bin/phpunit tests\n```\nAfter a while you will get the result, example:\n```\nOK (31 tests, 526577 assertions)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborutainfo%2Ftimebase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fborutainfo%2Ftimebase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborutainfo%2Ftimebase/lists"}