{"id":35031625,"url":"https://github.com/zcobell/fdate","last_synced_at":"2026-03-17T12:32:15.035Z","repository":{"id":294573816,"uuid":"983755326","full_name":"zcobell/fdate","owner":"zcobell","description":"Fortran Date/Time Library","archived":false,"fork":false,"pushed_at":"2025-07-30T20:33:51.000Z","size":251,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-12-28T21:19:39.049Z","etag":null,"topics":["datetime","fortran"],"latest_commit_sha":null,"homepage":"","language":"Fortran","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zcobell.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}},"created_at":"2025-05-14T21:39:59.000Z","updated_at":"2025-07-30T20:33:53.000Z","dependencies_parsed_at":"2025-05-22T08:45:34.546Z","dependency_job_id":null,"html_url":"https://github.com/zcobell/fdate","commit_stats":null,"previous_names":["zcobell/fdate"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zcobell/fdate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcobell%2Ffdate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcobell%2Ffdate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcobell%2Ffdate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcobell%2Ffdate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zcobell","download_url":"https://codeload.github.com/zcobell/fdate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zcobell%2Ffdate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30623662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T11:26:08.186Z","status":"ssl_error","status_checked_at":"2026-03-17T11:24:37.311Z","response_time":56,"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":["datetime","fortran"],"created_at":"2025-12-27T07:12:16.698Z","updated_at":"2026-03-17T12:32:15.022Z","avatar_url":"https://github.com/zcobell.png","language":"Fortran","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FDate Library\n[![CI](https://github.com/zcobell/fdate/actions/workflows/push.yaml/badge.svg)](https://github.com/zcobell/fdate/actions/workflows/push.yaml)\n[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-yellow.svg)](https://opensource.org/licenses/GPL-3.0)\n[![CMake](https://img.shields.io/badge/CMake-3.14%2B-blue.svg)](https://cmake.org/)\n[![Fortran](https://img.shields.io/badge/Fortran-2008%2B-blue.svg)](https://fortran-lang.org/)\n\nA modern datetime library for Fortran that provides comprehensive date and time manipulation capabilities through a clean Fortran interface built on top of Howard Hinnant's date library, which was used as the basis for `std::chrono` date operations in C++20.\n\n## Background\n\nThe FDate library bridges the gap between modern C++ datetime functionality and Fortran applications. While Fortran excels in scientific computing, it has traditionally lacked robust datetime manipulation capabilities. This library provides:\n\n- Millisecond precision datetime objects\n- TimeDelta objects for duration calculations\n- Comprehensive formatting and parsing with customizable format strings\n- Full operator overloading for natural datetime arithmetic\n- Memory-safe design using value types instead of pointers\n- Cross-platform compatibility\n\nThe library uses a design where both `t_DateTime` and `t_TimeDelta` objects are represented internally as 64-bit integers (milliseconds since epoch for `t_DateTime`, total milliseconds for `t_TimeDelta`), and avoids using any other in-memory structures in the interface between C++ and Fortran.\n\n## Features\n\n### DateTime Operations\n- Create dates from components (year, month, day, hour, minute, second, millisecond)\n- Parse dates from strings with custom format specifiers\n- Parse dates using arrays of format options (tries each format until one succeeds)\n- Parse with automatic format detection plus custom fallback formats\n- Format dates to strings (including ISO 8601)\n- Get current system time\n- Extract individual components (year, month, day, etc.)\n- Julian Day Number and Julian Day calculations for astronomical applications\n- Full comparison operators (`==`, `\u003c`, `\u003e`, `\u003c=`, `\u003e=`, `/=`)\n- Add/subtract TimeDeltas to/from DateTime objects\n\n### TimeDelta Operations\n- Create time deltas from various units (days, hours, minutes, seconds, milliseconds)\n- Extract components and total values\n- Arithmetic operations (addition, subtraction, multiplication, division)\n- Full comparison operators (`==`, `\u003c`, `\u003e`, `\u003c=`, `\u003e=`, `/=`)\n- String representation\n\n## Installation\n\n### Prerequisites\n- CMake 3.14 or higher\n- Modern C++ compiler supporting at least C++17\n- Fortran 2008 compiler (gfortran, ifort, etc.)\n\n### Building\n```bash\nmkdir build \u0026\u0026 cd build\ncmake .. -DCMAKE_INSTALL_PREFIX=/path/to/install\nmake \u0026\u0026 make install\n```\nThis will build a shared library and place it at the specified installation location. From there, you\ncan use it in your Fortran projects by linking against the installed library and including the Fortran \nmodule file in the installed include directory.\n\n### CMake Options\n- `FDATE_ENABLE_TESTING`: Enable testing suite (default: OFF)\n\n## Fortran Usage Examples\n\n### Basic DateTime Creation and Manipulation\n\n```fortran\nprogram datetime_examples\n   use mod_datetime, only: t_datetime, t_timedelta, now\n   implicit none\n   \n   type(t_datetime) :: dt1, dt2, current_time\n   type(t_timedelta) :: ts1, ts2, difference\n   character(len=64) :: date_string\n   \n   ! Create a specific datetime: January 15, 2024, 14:30:45.123\n   dt1 = t_datetime(2024, 1, 15, 14, 30, 45, 123)\n   \n   ! Create date-only (time defaults to 00:00:00.000)\n   dt2 = t_datetime(2024, 12, 25)\n   \n   ! Get current system time\n   current_time = now()\n   \n   ! Extract components\n   write(*,*) 'Year:', dt1%year()\n   write(*,*) 'Month:', dt1%month()\n   write(*,*) 'Day:', dt1%day()\n   write(*,*) 'Hour:', dt1%hour()\n   write(*,*) 'Minute:', dt1%minute()\n   write(*,*) 'Second:', dt1%second()\n   write(*,*) 'Millisecond:', dt1%millisecond()\n   \nend program datetime_examples\n```\n\n### TimeDelta Operations\n\n```fortran\nprogram timedelta_examples\n   use mod_datetime, only: t_timedelta, t_datetime, operator(+), operator(-), operator(*), operator(/)\n   implicit none\n   \n   type(t_timedelta) :: ts1, ts2, ts_result\n   type(t_datetime) :: dt_start, dt_end\n   \n   ! Create timedeltas from different units\n   ts1 = t_timedelta(days=2, hours=3, minutes=45, seconds=30, milliseconds=500)\n   ts2 = t_timedelta(hours=5)  ! 5 hours\n   \n   ! Arithmetic operations\n   ts_result = ts1 + ts2      ! Addition\n   ts_result = ts1 - ts2      ! Subtraction\n   ts_result = ts1 * 2        ! Multiplication\n   ts_result = ts1 / 2        ! Division\n   \n   ! Extract components\n   write(*,*) 'Days:', ts1%days()\n   write(*,*) 'Hours:', ts1%hours()\n   write(*,*) 'Total hours:', ts1%total_hours()\n   write(*,*) 'Total milliseconds:', ts1%total_milliseconds()\n   \n   ! Calculate difference between two dates\n   dt_start = t_datetime(2024, 1, 1, 9, 0, 0)\n   dt_end = t_datetime(2024, 1, 5, 17, 30, 0)\n   ts_result = dt_end - dt_start\n   \n   write(*,*) 'Time difference:', ts_result%to_string()\n   \nend program timedelta_examples\n```\n\n### Date Arithmetic and Comparisons\n\n```fortran\nprogram date_arithmetic\n   use mod_datetime, only: t_datetime, t_timedelta, operator(+), operator(-), operator(\u003c), operator(\u003e), operator(==)\n   implicit none\n   \n   type(t_datetime) :: meeting_time, deadline, reminder\n   type(t_timedelta) :: one_week, two_hours\n   \n   ! Set meeting time\n   meeting_time = t_datetime(2024, 6, 15, 14, 0, 0)  ! June 15, 2PM\n   \n   ! Create timedelta objects\n   one_week = t_timedelta(days=7)\n   two_hours = t_timedelta(hours=2)\n   \n   ! Calculate deadline (one week after meeting)\n   deadline = meeting_time + one_week\n   \n   ! Set reminder (2 hours before meeting)\n   reminder = meeting_time - two_hours\n   \n   ! Comparisons\n   if (reminder \u003c meeting_time) then\n      write(*,*) 'Reminder is set before the meeting'\n   end if\n   \n   if (deadline \u003e meeting_time) then\n      write(*,*) 'Deadline is after the meeting'\n   end if\n   \n   ! Check if dates are equal\n   if (meeting_time == meeting_time) then\n      write(*,*) 'Dates are identical'\n   end if\n   \nend program date_arithmetic\n```\n\n### String Formatting and Parsing\n\n```fortran\nprogram string_operations\n   use mod_datetime, only: t_datetime\n   implicit none\n   \n   type(t_datetime) :: dt, parsed_dt\n   character(len=64) :: formatted_string\n   \n   ! Create a datetime\n   dt = t_datetime(2024, 3, 14, 9, 26, 53, 589)\n   \n   ! Format to different string representations\n   formatted_string = dt%strftime('%Y-%m-%d %H:%M:%S')\n   write(*,*) 'Standard format: ', trim(formatted_string)\n   \n   formatted_string = dt%strftime('%B %d, %Y at %I:%M %p')\n   write(*,*) 'Verbose format: ', trim(formatted_string)\n   \n   ! ISO 8601 format\n   formatted_string = dt%to_iso_string()\n   write(*,*) 'ISO format: ', trim(formatted_string)\n   \n   ! Some Custom formats\n   formatted_string = dt%strftime('%A, %B %d, %Y') ! Full weekday and month names\n   write(*,*) 'Custom format: ', trim(formatted_string)\n   formatted_string = dt%strftime('%Y-%m-%dT%H:%M:%S',.true.) ! ISO with milliseconds\n   write(*,*) 'ISO with milliseconds: ', trim(formatted_string)\n   \n   ! Parse a date string\n   parsed_dt = t_datetime('2024-03-14 09:26:53', 'auto') ! Note, 'auto' as a format string is provided \n                                                         ! as a default if no format is specified \n  \n   ! Check if parsing was successful\n   if (parsed_dt%valid()) then\n       write(*,*) 'Parsed date: ', parsed_dt%strftime('%Y-%m-%d %H:%M:%S')\n   else\n       write(*,*) 'Failed to parse date string'\n   end if\n   \nend program string_operations\n```\n\n### Array-Based Parsing with Multiple Format Options\n\nThe library supports parsing with multiple format options, trying each format in order until one succeeds:\n\n```fortran\nprogram array_parsing_examples\n   use mod_datetime, only: t_datetime\n   implicit none\n   \n   type(t_datetime) :: parsed_dt\n   character(len=30) :: date_strings(3) = [ \u0026\n      '2024/03/14 09:26:53        ', \u0026  ! Slash-separated format\n      '14-Mar-2024 09:26:53       ', \u0026  ! Month name format  \n      '20240314092653             '  ]  ! Compact format\n   character(len=30) :: formats(4) = [ \u0026\n      '%Y/%m/%d %H:%M:%S          ', \u0026  ! Slash format\n      '%d-%b-%Y %H:%M:%S          ', \u0026  ! Month name format\n      '%Y%m%d%H%M%S               ', \u0026  ! Compact format\n      '%Y-%m-%d %H:%M:%S          '  ]  ! Standard format\n   integer :: i\n   \n   ! Try parsing with an array of format options\n   do i = 1, size(date_strings)\n      parsed_dt = t_datetime(trim(date_strings(i)), formats)\n      \n      if (parsed_dt%valid()) then\n         write(*,*) 'Successfully parsed: ', trim(date_strings(i))\n         write(*,*) 'Result: ', parsed_dt%strftime('%Y-%m-%d %H:%M:%S')\n      else\n         write(*,*) 'Failed to parse: ', trim(date_strings(i))\n      end if\n   end do\n\n   ! Parse with auto-detection and custom fallbacks\n   parsed_dt = t_datetime('2024.03.14T09:26:53', ['%Y.%m.%dT%H:%M:%S     ', \u0026\n                                                   '%Y.%m.%d %H:%M:%S     '])\n   \nend program array_parsing_examples\n```\n\n### Julian Day Calculations\n\nThe library provides Julian Day Number (JDN) and Julian Day (JD) calculations for astronomical applications:\n\n```fortran\nprogram julian_day_examples\n   use mod_datetime, only: t_datetime\n   implicit none\n   \n   type(t_datetime) :: dt\n   integer(kind=8) :: jdn\n   real(kind=8) :: jd\n   \n   ! Create datetime objects for well-known astronomical dates\n   \n   ! January 1, 2000 at noon UTC (J2000.0 epoch)\n   dt = t_datetime(2000, 1, 1, 12, 0, 0)\n   jdn = dt%julian_day_number()    ! Returns 2451545\n   jd = dt%julian_day()            ! Returns 2451545.0\n   \n   write(*,*) 'Y2K noon JDN:', jdn\n   write(*,*) 'Y2K noon JD:', jd\n   \n   ! January 1, 2000 at midnight UTC\n   dt = t_datetime(2000, 1, 1, 0, 0, 0)\n   jd = dt%julian_day()            ! Returns 2451544.5\n   write(*,*) 'Y2K midnight JD:', jd\n   \n   ! Current time with fractional day\n   dt = t_datetime(2025, 7, 24, 15, 30, 45, 500)\n   jdn = dt%julian_day_number()    ! Integer days since JD epoch\n   jd = dt%julian_day()            ! Fractional days including time\n   \n   write(*,*) 'Current JDN:', jdn\n   write(*,*) 'Current JD with time:', jd\n   \n   ! Julian Day calculations are useful for:\n   ! - Astronomical computations\n   ! - Converting between different calendar systems  \n   ! - High-precision time interval calculations\n   ! - Satellite orbital mechanics\n   \nend program julian_day_examples\n```\n\n**Julian Day Notes:**\n- Julian Day Number (JDN) is the integer count of days since January 1, 4713 BCE (proleptic Julian calendar)\n- Julian Day (JD) includes fractional time, where JD 0.0 begins at noon UTC\n- Commonly used in astronomy for precise time calculations\n- The library uses overflow-safe 64-bit integer arithmetic for reliability\n\n## Format Specifiers\n\nThe library supports typical format specifiers for date formatting:\n\n| Specifier | Description | Example |\n|-----------|-------------|---------|\n| `%Y` | 4-digit year | 2024 |\n| `%m` | Month (01-12) | 03 |\n| `%d` | Day of month (01-31) | 14 |\n| `%H` | Hour (00-23) | 09 |\n| `%M` | Minute (00-59) | 26 |\n| `%S` | Second (00-59) | 53 |\n| `%B` | Full month name | March |\n| `%A` | Full weekday name | Thursday |\n\n## Error Handling\n\nThe library handles errors gracefully:\n- Invalid date parameters return special error timestamps\n- Parsing failures are indicated by returned error values\n\n## Thread Safety\n\nThe library is thread-safe for read operations. For write operations in multi-threaded environments, appropriate synchronization should be implemented by the calling application.\n\n## Contributing\n\nContributions are welcome! Please ensure that:\n- All new features include appropriate test cases\n- Code follows the existing style conventions\n- Documentation is updated for new functionality\n\n## License\n\nThis project is licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details.\n\n## Support\n\nFor questions, bug reports, or feature requests, please create an issue in the project repository.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcobell%2Ffdate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzcobell%2Ffdate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzcobell%2Ffdate/lists"}