



  

<!DOCTYPE html>
<html
  lang="en"
  
  data-color-mode="auto" data-light-theme="light" data-dark-theme="dark"
  data-a11y-animated-images="system" data-a11y-link-underlines="true"
  
  >




  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">

<script type="importmap">{"imports":{"react":"https://github.githubassets.com/assets/react-e27d1b3e03961e68.js","react-dom":"https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js","react-dom/client":"https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js","react-is":"https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js","react-reconciler":"https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js","react/compiler-runtime":"https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js","react/jsx-dev-runtime":"https://github.githubassets.com/assets/react-jsx-dev-runtime-ea55d68667d559e5.js","react/jsx-runtime":"https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js","scheduler":"https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js"}}</script>
<meta name="react-profiling" content="0" data-turbo-transient="true" />
<meta name="react-import-map" content="react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@777f63f87cd0" data-turbo-track="reload" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-e27d1b3e03961e68.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js" />

  


  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-0f910d8806d5761b.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-a7abd4d4c49ac593.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-5fc4c4a9cb41e596.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-ed0cee9214dedabd.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-78a2491d538dab5a.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-c26b63d7c532d0a2.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-a6f60cea68c08405.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-f66faf28b2ea18b6.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-6701f6218c53cf5b.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-7037fa46ae124d97.css" />

  <style type="text/css">
    :root {
      --tab-size-preference: 4;
    }

    pre, code {
      tab-size: var(--tab-size-preference);
    }
  </style>

    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-97df7784617ce1ea.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-9be9fe6313f476af.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-62747e27e61258dc.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-b04ca6fccda778e2.css" />
  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-72bd7d974b5ac1cc.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-4c5c0895f723f870.css" />

  

  <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_caches_react_shell","actions_enable_background_steps","actions_new_hosted_runner_image_select_sizes_and_versions","actions_runners_react_shell","agent_author_search_expansion","agent_author_search_expansion_ui_pulls","alternate_user_config_repo","async_conversion_coverage_enabled","billing_billable_licenses_cost_center_bucket_fix","billing_budget_expiration","billing_cost_center_list_assigned_resources","billing_discount_threshold_notification","code_quality_enablement_banner_targeting","code_quality_remove_preview","code_view_raf_sticky_lines","codespaces_prebuild_region_target_update","coding_agent_third_party_model_ui","copilot_agent_snippy","copilot_ahp_tool_call_timing","copilot_api_agentic_issue_marshal_yaml","copilot_automation_repo_mcp_servers","copilot_automations_pagination","copilot_base_model_policy_row","copilot_chat_auto_mode_v2","copilot_chat_clear_model_selection_for_default_change","copilot_chat_early_task_provisioning","copilot_chat_persist_session_drafts","copilot_chat_vision_dotcom_chat_ga_gate","copilot_css_textarea_autosize","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_removal_on_marketplace","copilot_fix_failed_workflows_all_skus","copilot_hide_hovercard","copilot_immersive_task_hyperlinking","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_merge_fix_ci","copilot_mission_control_agent_merge_resolve_conflicts","copilot_mission_control_awps_batching","copilot_mission_control_early_stop","copilot_mission_control_managed_sandbox_environments","copilot_mission_control_needs_attention","copilot_mission_control_reasoning_effort","copilot_mission_control_sandbox_remote_bypass","copilot_mission_control_task_alive_updates","copilot_mission_control_task_sharing","copilot_org_policy_page_focus_mode","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_swe_agent_authorization_status_ui","copilot_swe_agent_automation_resource_scoped_writes","copilot_swe_agent_discussion_comment_trigger","copilot_swe_agent_discussion_opened_trigger","copilot_swe_agent_discussion_updated_trigger","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_issue_assigned_trigger","copilot_swe_agent_issue_comment_trigger","copilot_swe_agent_issue_labeled_trigger","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_assigned_trigger","copilot_swe_agent_pull_request_comment_trigger","copilot_swe_agent_pull_request_labeled_trigger","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_ready_for_review_trigger","copilot_swe_agent_pull_request_review_requested_trigger","copilot_swe_agent_pull_request_review_submitted_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_sub_issue_added_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_task_scoped_alive_channel","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_user_can_upgrade_plan_field","copilot_web_integration_cutover","copilot_workbench_sunset_redirect","dashboard_agents_module_auth_token_check","dashboard_indexeddb_caching","fgpat_permissions_selector_redesign","glc_code_quality_repo_settings_workflow_config","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","in_product_messaging_datadog_monitoring","ipm_ubb_individual_budget_banner","issue_fields_multi_select","issue_inline_avatars","issue_pinned_views","issue_pinned_views_team_vs_personal","issue_relative_time_micro","issue_viewer_paved_path","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","labels_archiving","labels_archiving_info","landing_pages_ninetailed","lifecycle_label_name_updates","marketing_cookie_consent_banner","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_queue_restricted_pushers_warning","merge_status_header_feedback","milestone_closed_issues_prioritization","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","primer_react_timeline_list_semantics","prs_copilot_app_open_action","prs_css_anchor_positioning","pull_request_copilot_attribution_header","pull_request_overview_merge_control","pull_request_overview_panel_edit_description","pull_request_persister","pull_request_stacks_navigation_shortcuts","pull_request_virtualization_image_estimate","pull_request_virtualization_loader_batching","pull_request_virtualization_scroll_compensation","pull_request_virtualization_scroll_intent","quick_search_lazy_suggestions","react_blob_isolate_code_lines","react_blob_ssr_content_visibility","react_data_router_tanstack_allowed","react_logged_out_repository_header","react_query_props_with_key","react_sandbox_future_tanstack","repo_app_turbo","repo_issues_sidebar_layout","repo_pulls_dashboard_declutter","repo_pulls_dashboard_ga","repo_pulls_dashboard_persistence","repos_contributors_limited_default_range","review_involves_filter","rule_ignored_file_paths","rulesets_actor_list_editor","sample_network_conn_type","security_center_artifact_filters_popover","see_who_reacted","semantic_similarity_duplicate_issue_detection","session_logs_ungroup_reasoning_text","set_sha256_on_repo_creation_form","site_banner_desktop_copilot_app","site_ghca_pixel_mona","site_github_app_ga_page","site_github_app_ga_page_highlight","site_github_app_mobile_native_share","site_global_banner_dev_days_attendee","site_global_nav_spark_models_removed","speculation_rules_ui_service","suggest_custom_property_values_copilot","suppress_automated_browser_vitals","swp_forms_disable_octocaptcha","thread_resolution_reason","update_issue_suggestions","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workstream_plugin_bootstrap"],"githubDomain":"https://github.com","copilotApiOverrideUrl":"https://api.githubcopilot.com","cmcApiUrl":"https://api.github.com/cmc_internal/api"}</script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/high-contrast-cookie-3663bcaacc724f4c.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-721126455a2225e3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-156c6259e31cc551.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-f6ce38f47c2e1d56.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-804a14996977c014.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-fb5d13278eb42203.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tp-ea613009a991e211.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-107a7753389a8a2d.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.25915bc98fb322a6.module.css" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/catalyst-52ed81112a548e10.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/selector-observer-e8810f64c443fb9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/relative-time-element-fe7e72f699fdf493.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/by-9da36843ba9d191d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ja9-9a1160b939f2cd52.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3h-55903cf2303047ad.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hk-0d35a1220587d888.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-c964b1a3671f2a92.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hj-1d800d09e9a8720a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j0-1ad12374da9777f2.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-531d35538b61fd0d.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-bf5e3b2aee197122.js" defer="defer"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/runtime-helpers-5e0b3ae3c4036207.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/aria-live-752acdc868e2da64.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-e87ffadced20a3c9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-75bc55d9971828b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a9-34620c7b13885011.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ur-643d2814115561a9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t6-5d0869970ac0aac0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pb0-a5c5ec36d311aeef.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6n-afcf86ccabc4cad2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zj-f08c728cf00018aa.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/o6-2a1c68d269710ee9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/h9a-c6405aa090de0e84.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vy6-3c3e6e96629c2ce4.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/js-4eb97d5803e657c0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/g7-baf9e817ae102b01.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/unc-96389cade7bad821.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nu-65322a6997c6c93c.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-5dd3809b5c8bac3c.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.3792087592bf207a.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-4318f0f4c608f3dd.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-7afef75d393cf294.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/op-acddf38478d45ef9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ncx-461e4b09f2e67ee5.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qmp-c7cfba40cf5a93b0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j6-148a74299e5a01ab.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t7l-a52ba56147f77909.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4u-ec4874f70bfd5d76.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s0-481bd34f90bc2bd7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y5-ed17e73b4c0bd15e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4-be595475cdbf7d4b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8-23a3c5ff8eef412d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/la-27679061f16e1495.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iu-9806a0291a782cbe.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ftx-39fb490e3c1d778f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zi-32a0c3c081ea5cce.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sg-7a5d50475874c0e1.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pd-6a8710840033e042.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/86g-ec28c25ed7d5de06.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sn-1bab7384818953b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iq-6d4ecf6d2fb6993c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2-7d8e7cee5b46cb45.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7d-2e3cc25d719f3a95.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4d-76d8acdf21a33266.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tsb-e0f6288ab985d9d2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lf-910ef220ce85c660.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2j-2f19c1afd2ceaf93.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/me-f1476ec44a29f34a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2u-e654a57b1a70c47d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5d-d97cc006d4da4d9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r5-38f013bc2c0fd298.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r6s-9039f5619230a653.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/9e-cece06724bf6ea3b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/x9-3e077a3a37a73f9f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pj-87629cb5389d7663.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/eq-3764fd5f66494289.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/13-d889936dff7e5c0f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/44-8193eea4af825ead.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/v4-9c1327d212e52a0d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/id-7f39706ba9007db6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ah-271362a1ed227d03.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s1g-d434d712bca59d3a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vz-d7f4a583896f872e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/47-c8c0ce2700acc5be.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-4118a687d0150749.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ah.2623f7c6ecbe2ecd.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/47.78770c57a48a810c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.37656c95a9729fb9.module.css" />


  <title>jiff/COMPARE.md at master · jif-oai/jiff · GitHub</title>



  <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient>
  <meta name="route-controller" content="blob" data-turbo-transient>
  <meta name="route-action" content="show" data-turbo-transient>
  <meta name="fetch-nonce" content="v2:64fc5e07-7204-3f0d-8f84-d8ea5f8ac6cd">

    
  <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb">


  <meta name="request-id" content="9604:27A019:B4D8110:EB963D8:6ACA6683" data-pjax-transient="true"/><meta name="html-safe-nonce" content="c88298ee06ac1aafe77999060b8cb0100abbfb9c6097d91f3202d5059fb0c1ea" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NjA0OjI3QTAxOTpCNEQ4MTEwOkVCOTYzRDg6NkFDQTY2ODMiLCJ2aXNpdG9yX2lkIjoiMjI0MDczMzU5MTcyMDU4NDgzNSIsInJlZ2lvbl9lZGdlIjoiZnJhIiwicmVnaW9uX3JlbmRlciI6ImZyYSJ9" data-pjax-transient="true"/><meta name="visitor-hmac" content="3bc50a7e0d61db3ebd9eacda27d9eea7c88b958fd9d51b5bfa2989a029725f51" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:1315094102" data-turbo-transient>


  <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" />
  

  <meta name="selected-link" value="repo_source" data-turbo-transient>
  <link rel="assets" href="https://github.githubassets.com/">

    <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I">

<meta name="octolytics-url" content="https://collector.github.com/github/collect" />





  <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" />

  




    <meta name="user-login" content="">

  

    <meta name="viewport" content="width=device-width">

    

      <meta name="description" content="A datetime library for Rust that encourages you to jump into the pit of success. - jiff/COMPARE.md at master · jif-oai/jiff">

      <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">

    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
    <meta property="fb:app_id" content="1401488693436528">
    <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/jif-oai/jiff/blob/master/COMPARE.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/fbf08a9da86e7aa6b2d87af22e880469f0e43101863ff532ff18a5977dee9bf4/jif-oai/jiff" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="jiff/COMPARE.md at master · jif-oai/jiff" /><meta name="twitter:description" content="A datetime library for Rust that encourages you to jump into the pit of success. - jif-oai/jiff" />
  <meta property="og:image" content="https://opengraph.githubassets.com/fbf08a9da86e7aa6b2d87af22e880469f0e43101863ff532ff18a5977dee9bf4/jif-oai/jiff" /><meta property="og:image:alt" content="A datetime library for Rust that encourages you to jump into the pit of success. - jif-oai/jiff" /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="jiff/COMPARE.md at master · jif-oai/jiff" /><meta property="og:url" content="https://github.com/jif-oai/jiff/blob/master/COMPARE.md" /><meta property="og:description" content="A datetime library for Rust that encourages you to jump into the pit of success. - jif-oai/jiff" />
  




      <meta name="hostname" content="github.com">



        <meta name="expected-hostname" content="github.com">


  <meta http-equiv="x-pjax-version" content="d05be8f8b6905b6460fc264e80447721dfee1e32cf9e4291c4bf58f160c9f705" data-turbo-track="reload">
  <meta http-equiv="x-pjax-csp-version" content="c4a65e47b0c850e1157ae8e66298070851d7e3b558038de5a3b4ff7a93e630ed" data-turbo-track="reload">
  <meta http-equiv="x-pjax-css-version" content="a80b0545b169f440b929ce2b977c76b6988f014cca6513fb83c5df6581635fb3" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="af51c6f9d659be0324665373df3ee542f817dbd7f66f352a087935f2ceabe545" data-turbo-track="reload">

  <meta name="turbo-cache-control" content="no-preview" data-turbo-transient="">

      <meta name="turbo-cache-control" content="no-cache" data-turbo-transient>

    <meta data-hydrostats="publish">

  <meta name="go-import" content="github.com/jif-oai/jiff git https://github.com/jif-oai/jiff.git">

  <meta name="octolytics-dimension-user_id" content="230027070" /><meta name="octolytics-dimension-user_login" content="jif-oai" /><meta name="octolytics-dimension-repository_id" content="1315094102" /><meta name="octolytics-dimension-repository_nwo" content="jif-oai/jiff" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="true" /><meta name="octolytics-dimension-repository_parent_id" content="759017108" /><meta name="octolytics-dimension-repository_parent_nwo" content="BurntSushi/jiff" /><meta name="octolytics-dimension-repository_network_root_id" content="759017108" /><meta name="octolytics-dimension-repository_network_root_nwo" content="BurntSushi/jiff" />
  



    

    <meta name="turbo-body-classes" content="logged-out env-production page-responsive">
  <meta name="disable-turbo" content="false">


  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">


  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">

  <meta name="release" content="3b1bb5b10f5c7fd1769d56e38b15dfddb34052a8" data-turbo-track="reload">
  <meta name="ui-target" content="full">

  <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000">
  <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png">
  <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon">

<meta name="theme-color" content="#1e2327">
<meta name="color-scheme" content="light dark" />


  <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">

  </head>

  <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
    <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
      <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div>
      

    <div class="position-relative header-wrapper js-header-wrapper ">
      <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a>

      <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full">
    <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span>
</span>      
      <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/19-c660652a0a1639be.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-47c5223d8d1af8ef.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.d53d993320d57e14.module.css" />

<react-partial
  partial-name="keyboard-shortcuts-dialog"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>





      

          <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-install-banner-partial-3c87deb7f0f20434.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-install-banner-partial.7b357012e82003e7.module.css" />

<react-partial
  partial-name="app-install-banner-partial"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>


          

                <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/et9-7eeec247c287fca4.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/94v-e20946127faa8f6e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz5-892a9e99cc92858d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jag-441e702bfd4c7904.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hw-8ce7888b57d0a23c.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/rq-0ec82a12cf538a4d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1m-a7a4c022483b2713.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-70703fe17422eb58.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.fbc35b3d20e988ff.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/1m.fec8b575d0e5234f.module.css" />

<react-partial
  partial-name="marketing-header"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"color_mode":"dark","logged_in":false,"marketing_page":false,"home_path":"/","login_path":"/login?return_to=https%3A%2F%2Fgithub.com%2Fjif-oai%2Fjiff%2Fblob%2Fmaster%2FCOMPARE.md","signup_path":"/signup?ref_cta=Sign+up\u0026ref_loc=header+logged+out\u0026ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow\u0026source=header-repo\u0026source_repo=jif-oai%2Fjiff","signup_enabled":true,"is_signup_controller":false,"show_search_and_nav":true,"hide_search":false,"private_mode_enabled":false,"should_use_dotcom_links":true,"auth_hydro_click":"{\"event_type\":\"authentication.click\",\"payload\":{\"location_in_page\":\"site header menu\",\"repository_id\":null,\"auth_type\":\"SIGN_UP\",\"originating_url\":\"https://github.com/jif-oai/jiff/blob/master/COMPARE.md\",\"user_id\":null}}","auth_hydro_click_hmac":"7a5ccaaf7779c46c68eea6fa5a102b8030610d56efda0c9f317cf1859152c067","overlay":false,"fixed":false}}</script>
  <div data-target="react-partial.reactRoot"><div data-color-mode="dark" data-light-theme="light" data-dark-theme="dark"><header class="MarketingHeader-module__root__Tk7n3 HeaderMktg header-logged-out" role="banner" data-marketing-header="true" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" data-is-top="true"><h2 class="MarketingHeader-module__visuallyHidden__sqKsl">Navigation Menu</h2><button type="button" class="MarketingHeader-module__backdrop__sw4RU" aria-label="Close navigation menu"></button><div class="MarketingHeader-module__bar__mBSyE"><div class="MarketingHeader-module__topRow__yeury"><div class="MarketingHeader-module__toggleSlot__hDxbh"><button type="button" class="HeaderMenuToggle-module__toggle__i8EiC" aria-label="Toggle navigation" aria-expanded="false"><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span></button></div><a href="/" aria-label="Homepage" class="HeaderLogo-module__logo__UFyHI" data-analytics-event="{&quot;action&quot;:&quot;homepage&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;logo&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;homepage_link_logo_header&quot;}"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github" viewBox="0 0 24 24" width="32" height="32" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path></svg></a><div class="AuthCTAs-module__mobileActions__NNzeV"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/login?return_to=https%3A%2F%2Fgithub.com%2Fjif-oai%2Fjiff%2Fblob%2Fmaster%2FCOMPARE.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/jif-oai/jiff/blob/master/COMPARE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="7a5ccaaf7779c46c68eea6fa5a102b8030610d56efda0c9f317cf1859152c067"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_3dd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_3dd_">Appearance settings</div></div></div><div class="MarketingHeader-module__menu__GIy3y"><div class="MarketingHeader-module__menuWrapper__owstH"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_nd_">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5knd_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>GitHub Copilot</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Write better code with AI</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/ai/github-app" data-analytics-event="{&quot;action&quot;:&quot;github_copilot_app&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_app_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656"></path></svg>GitHub Copilot app</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Direct agents from issue to merge</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.52 1.12a3.578 3.578 0 0 1 6.078 2.98 3.578 3.578 0 0 1 2.982 6.08l-3.292 3.293a.252.252 0 0 0 0 .354l.843.843a.749.749 0 1 1-1.06 1.06l-.844-.843a1.75 1.75 0 0 1 0-2.474L13.52 9.12a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0L7.731 9.03A.75.75 0 0 1 6.67 7.97l2.85-2.85a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0l-4.799 4.8A.75.75 0 0 1 .72 5.92Z"></path><path d="M7.52 3.12a.749.749 0 1 1 1.06 1.06L5.731 7.03A2.079 2.079 0 0 0 8.67 9.97l2.85-2.85a.749.749 0 1 1 1.06 1.06l-2.849 2.85A3.578 3.578 0 0 1 4.67 5.97Z"></path></svg>MCP Registry</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Integrate external tools</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9knd_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path></svg>Actions</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Automate any workflow</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg>Codespaces</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Instant dev environments</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg>Issues</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Plan and track work</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg>Code Review</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Manage code changes</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-quality" data-analytics-event="{&quot;action&quot;:&quot;code_quality&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_quality_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codescan-checkmark NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.28 6.28a.75.75 0 1 0-1.06-1.06L6.25 8.19l-.97-.97a.75.75 0 0 0-1.06 1.06l1.5 1.5a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M7.5 15a7.5 7.5 0 1 1 5.807-2.754l2.473 2.474a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2.474-2.473A7.472 7.472 0 0 1 7.5 15Zm0-13.5a6 6 0 1 0 4.094 10.386.748.748 0 0 1 .293-.292 6.002 6.002 0 0 0 1.117-6.486A6.002 6.002 0 0 0 7.5 1.5Z"></path></svg>Code Quality</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enforce quality at merge</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dknd_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>Code security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Secure your code as you build</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>Secret protection</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_hknd_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Why GitHub</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Blog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Changelog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all features</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_17d_">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_17d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5l7d_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Enterprises</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Small and medium teams</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Startups</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9l7d_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">App Modernization</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevSecOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">CI/CD</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all use cases</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dl7d_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dl7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Healthcare</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Financial services</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Manufacturing</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Government</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all industries</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all solutions</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_1nd_">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_1nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5lnd_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">AI</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Software Development</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all topics</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9lnd_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer stories</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Events &amp; webinars</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Ebooks &amp; reports</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Business insights</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Skills</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dlnd_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dlnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer support</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Community forum</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trust center</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all resources</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_27d_">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_27d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5m7d_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/open-source/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>GitHub Sponsors</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Fund open source developers</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9m7d_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security Lab</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Maintainer Community</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Stars</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Archive Program</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dm7d_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dm7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Topics</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trending</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_2nd_">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_2nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5mnd_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.122.392a1.75 1.75 0 0 1 1.756 0l5.003 2.902c.83.481.83 1.68 0 2.162L8.878 8.358a1.75 1.75 0 0 1-1.756 0L2.119 5.456a1.251 1.251 0 0 1 0-2.162ZM8.125 1.69a.248.248 0 0 0-.25 0l-4.63 2.685 4.63 2.685a.248.248 0 0 0 .25 0l4.63-2.685ZM1.601 7.789a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0L1.874 8.814A.75.75 0 0 1 1.6 7.789Zm0 3.5a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0l-5.248-3.044a.75.75 0 0 1-.273-1.025Z"></path></svg>Enterprise platform</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9mnd_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>Copilot for Business</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg>Premium Support</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></span></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="MarketingNavigation-module__navLink__hUomM">Pricing</a></li></ul></nav><div class="MarketingHeader-module__ctaContainer__tBmPz"><div class="HeaderSearch-module__searchSlot__oVOUS"><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderSearch-module__trigger__zsF9q" type="button" aria-haspopup="dialog" aria-expanded="false" aria-label="Search or jump to, type / to search" data-analytics-event="{&quot;action&quot;:&quot;searchbar&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;context&quot;:&quot;global&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"><span class="HeaderSearch-module__content__kMpxU"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search HeaderSearch-module__icon__wcrHX" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg><span class="HeaderSearch-module__label__d1iWG">Search</span><kbd class="HeaderSearch-module__kbd__HNG0o" aria-hidden="true">/</kbd></span></span></span></button><div class="d-none"></div></div><div class="AuthCTAs-module__signInWrap__q2P60"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq AuthCTAs-module__desktopActionGap__UZuXT AuthCTAs-module__hiddenBelowLg__BfKBw" href="/login?return_to=https%3A%2F%2Fgithub.com%2Fjif-oai%2Fjiff%2Fblob%2Fmaster%2FCOMPARE.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/jif-oai/jiff/blob/master/COMPARE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="7a5ccaaf7779c46c68eea6fa5a102b8030610d56efda0c9f317cf1859152c067"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a></div><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--secondary___gHnw_ Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=jif-oai%2Fjiff" data-analytics-event="{&quot;action&quot;:&quot;sign_up&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_up_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/jif-oai/jiff/blob/master/COMPARE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="7a5ccaaf7779c46c68eea6fa5a102b8030610d56efda0c9f317cf1859152c067"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-secondary___eJ0_a">Sign up</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_fbd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_fbd_">Appearance settings</div></div></div></div></div><div class="MarketingHeader-module__bottomBorder__uZT38" aria-hidden="true"></div></header></div></div>
</react-partial>



      <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full">
  
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>

    <button id="icon-button-7385c0f4-50f7-4271-a862-2820fec8e26b" aria-labelledby="tooltip-649b3b99-3ba6-488d-9439-0eec1a7ff0a3" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
</button><tool-tip id="tooltip-649b3b99-3ba6-488d-9439-0eec1a7ff0a3" for="icon-button-7385c0f4-50f7-4271-a862-2820fec8e26b" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip>


  
</div>
    </div>

  <div id="start-of-content" class="show-on-focus"></div>








    <div id="js-flash-container" class="flash-container" data-turbo-replace>






  <template class="js-flash-template">
    
<div class="flash flash-full   {{ className }}">
  <div >
    <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    <div aria-atomic="true" role="alert" class="js-flash-alert">
      
      <div>{{ message }}</div>

    </div>
  </div>
</div>
  </template>
</div>


    






  <div
    class="application-main "
    data-commit-hovercards-enabled
    data-discussion-hovercards-enabled
    data-issue-and-pr-hovercards-enabled
    data-project-hovercards-enabled
  >
        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
    <main id="js-repo-pjax-container" >
      
      








  

    <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ym-6bc2c9bf8112c038.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sk2-8deeef9351be3911.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ni-3e194d222c7770bf.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7x-71d30cb240cd901f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wwk-ad869086822937b1.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a1-9f79841ecac1da8e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wzg-40a3213b3e83400b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5f-64f8e7d5bcbd4787.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/z5-b53a93078d026f1e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/8h-cef26f68c1331011.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fq-3ce13a77e863807a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a7-596b507bd20acddc.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xfx-c82d8352413aea0a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j4-b3a9e87fa7878a98.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/global-nav-bar-29c7aef68ee9db41.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-nav-bar.2f2560cba06ab359.module.css" />

<react-partial
  partial-name="global-nav-bar"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"contextRegion":{"crumbs":[{"crumb_type":"user","label":"jif-oai","is_root":false,"href":"/jif-oai"},{"crumb_type":"repository","label":"jiff","is_root":false,"octicon":"repo-forked","href":"/jif-oai/jiff"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/jif-oai/jiff","selectedLinks":["repo_source","repo_downloads","repo_commits","repo_releases","repo_tags","repo_branches","repo_packages","repo_deployments","repo_attestations"],"popoverTarget":false,"commandId":"repositories:go-to-code","reactNav":{"appTarget":"code-view","anchor":"code-view-repo-link"},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"pull-requests","icon":"git-pull-request","label":"Pull requests","href":"/jif-oai/jiff/pulls","selectedLinks":["repo_pulls","checks"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-pull-requests","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"actions","icon":"play","label":"Actions","href":"/jif-oai/jiff/actions","selectedLinks":["repo_actions"],"popoverTarget":false,"commandId":"repositories:go-to-actions","reactNav":{"appTarget":"actions-workflows","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"projects","icon":"table","label":"Projects","href":"/jif-oai/jiff/projects","selectedLinks":["repo_projects","new_repo_project","repo_project"],"popoverTarget":false,"commandId":"repositories:go-to-projects","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"security-and-quality","icon":"shield","label":"Security and quality","href":"/jif-oai/jiff/security","selectedLinks":["security","overview","alerts","policy","token_scanning","code_scanning"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-security","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"insights","icon":"graph","label":"Insights","href":"/jif-oai/jiff/pulse","selectedLinks":["repo_graphs","repo_contributors","dependency_graph","dependabot_updates","pulse","people","community"],"popoverTarget":false,"commandId":"repositories:go-to-insights","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}}],"localNavigationUpdateChannel":null,"selectedLink":"repo_source"},"owner":null,"headerLogo":{"href":"/","aria-label":"Homepage "},"notifications":{"indicatorMode":"disabled","websocketChannel":null,"fetchIndicatorSrc":"/notifications/indicator","fetchIndicatorEnabled":false},"issues":{"href":"/issues"},"pulls":{"href":"/pulls"},"contributedRepos":{"href":"/repos"},"copilot":{"show":false,"showAgentsButton":false,"showRelaunchAnnouncement":false,"copilotChatUrl":null,"copilotApiUrl":"https://api.githubcopilot.com"},"search":{"show":true,"showCommandPalette":false,"isSearchPage":false,"isJumpToSearch":false,"searchContext":{"scope":"repo:jif-oai/jiff","current_repo_name":"jiff","current_repo_nwo":"jif-oai/jiff","user_id":"jif-oai"}},"commandPalette":null,"enterpriseBar":{"show":false},"globalTransactionalMessage":[],"payloadsUrl":"/_global-navigation/payloads.json?can_toggle_site_admin_and_employee_status=0\u0026is_admin_mode_on=0\u0026is_ui_opted_out=0\u0026show_ui_opt_out=0\u0026v=7","contextRegionUrl":"/_global-navigation/context-region.json"}}</script>
  <div data-target="react-partial.reactRoot"><header aria-label="Global navigation menu" data-component="Stack" class="GlobalNav styles-module__appHeader__YzYWk prc-Stack-Stack-UQ9k6" data-gap="none" data-direction="vertical" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="none"><div data-component="Stack" class="prc-Stack-Stack-UQ9k6" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="center" data-padding="none"><div data-testid="top-nav-center" data-component="Stack" class="styles-module__center__R3QRv styles-module__withLocalNavigation__rjTJ_ GlobalNavBar-module__loggedOut__Jv1rk prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="normal"><nav class="styles-module__contextRegion__VbSp2 prc-Breadcrumbs-BreadcrumbsBase-3Gb-B" aria-label="Breadcrumbs" data-overflow="menu" data-variant="normal" data-component="Breadcrumbs"><ol class="prc-Breadcrumbs-BreadcrumbsList-BKjpe"><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/jif-oai" data-discover="true"><span class="">jif-oai</span></a></li><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/jif-oai/jiff" data-discover="true"><span class="styles-module__contextCrumbLast__tI2e3">jiff</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-repo-forked styles-module__trailingIcon__sCKDh" viewBox="0 0 16 16" width="12" height="12" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path></svg></a></li></ol></nav></div><div data-testid="top-nav-right" data-component="Stack" class="styles-module__right__mlBQg styles-module__withLocalNavigation__rjTJ_ styles-module__rightWithResponsiveCreateButton__SKn2W prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="start" data-padding="normal"></div></div><h2 class="prc-src-InternalVisuallyHidden-2YaI6">Repository navigation</h2><nav class="prc-components-UnderlineWrapper-eT-Yj prc-UnderlineNav-UnderlineWrapper-GWONT LocalNavigation-module__LocalNavigation__b0Xc0" aria-label="Repository" data-variant="inset" data-overflow-mode="wrap" data-hide-icons-breakpoint="medium"><ul class="prc-UnderlineNav-ItemsList-oj8gN prc-components-UnderlineItemList-xKlKC" role="list"><li role="presentation" aria-hidden="true" class="prc-UnderlineNav-WrapSpacer--aLgz"></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a aria-current="page" data-tab-item="code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg></span><span data-component="text" data-content="Code">Code</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="pull-requests" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff/pulls" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path></svg></span><span data-component="text" data-content="Pull requests">Pull requests</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="actions" data-react-nav="actions-workflows" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff/actions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-play" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg></span><span data-component="text" data-content="Actions">Actions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="projects" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff/projects" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-table" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path></svg></span><span data-component="text" data-content="Projects">Projects</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="security-and-quality" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff/security" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg></span><span data-component="text" data-content="Security and quality">Security and quality</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="insights" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/jif-oai/jiff/pulse" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-graph" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg></span><span data-component="text" data-content="Insights">Insights</span></a></li></ul><div class="prc-UnderlineNav-MoreButtonContainer-Dnrq6"><div class="prc-UnderlineNav-MoreButtonDivider-dN0a-"></div><button data-component="overflow-menu-button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk prc-UnderlineNav-MoreButton-Y8soj" data-loading="false" data-size="medium" data-variant="invisible" id="_R_2ktp_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><span>More<span class="prc-src-InternalVisuallyHidden-2YaI6"> items</span></span></span></span><span data-component="trailingAction" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></button></div></nav><div class="d-none"></div></header></div>
</react-partial>


  



<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class="">
    <div id="repo-content-pjax-container" class="repository-content " >
    



    
      
    








<react-app
  app-name="code-view"
  initial-path="/jif-oai/jiff/blob/master/COMPARE.md"
  style="display: block; min-height: calc(100vh - 64px);"
  data-attempted-ssr="true"
  data-ssr="true"
  data-lazy="false"
  data-alternate="false"
  data-data-router-enabled="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":1,"text":"Comparison with other Rust datetime crates","anchor":"comparison-with-other-rust-datetime-crates","htmlText":"Comparison with other Rust datetime crates"},{"level":2,"text":"chrono (v0.4.38)","anchor":"chrono-v0438","htmlText":"chrono (v0.4.38)"},{"level":3,"text":"Time zone database integration","anchor":"time-zone-database-integration","htmlText":"Time zone database integration"},{"level":3,"text":"Jiff losslessly roundtrips time zone aware datetimes","anchor":"jiff-losslessly-roundtrips-time-zone-aware-datetimes","htmlText":"Jiff losslessly roundtrips time zone aware datetimes"},{"level":3,"text":"Jiff provides support for zone aware calendar arithmetic","anchor":"jiff-provides-support-for-zone-aware-calendar-arithmetic","htmlText":"Jiff provides support for zone aware calendar arithmetic"},{"level":3,"text":"Jiff losslessly roundtrips durations","anchor":"jiff-losslessly-roundtrips-durations","htmlText":"Jiff losslessly roundtrips durations"},{"level":3,"text":"Jiff supports dealing with gaps in civil time","anchor":"jiff-supports-dealing-with-gaps-in-civil-time","htmlText":"Jiff supports dealing with gaps in civil time"},{"level":3,"text":"Jiff supports rounding durations","anchor":"jiff-supports-rounding-durations","htmlText":"Jiff supports rounding durations"},{"level":3,"text":"Jiff supports zone-aware rounding of durations","anchor":"jiff-supports-zone-aware-rounding-of-durations","htmlText":"Jiff supports zone-aware rounding of durations"},{"level":3,"text":"Jiff supports re-balancing durations","anchor":"jiff-supports-re-balancing-durations","htmlText":"Jiff supports re-balancing durations"},{"level":3,"text":"Jiff supports getting the nth weekday from the current date","anchor":"jiff-supports-getting-the-nth-weekday-from-the-current-date","htmlText":"Jiff supports getting the nth weekday from the current date"},{"level":3,"text":"Jiff supports detecting time zone offset conflicts","anchor":"jiff-supports-detecting-time-zone-offset-conflicts","htmlText":"Jiff supports detecting time zone offset conflicts"},{"level":3,"text":"Jiff supports adding durations with calendar units","anchor":"jiff-supports-adding-durations-with-calendar-units","htmlText":"Jiff supports adding durations with calendar units"},{"level":3,"text":"Jiff supports zone-aware re-balancing of durations","anchor":"jiff-supports-zone-aware-re-balancing-of-durations","htmlText":"Jiff supports zone-aware re-balancing of durations"},{"level":3,"text":"Jiff is generally faster than Chrono","anchor":"jiff-is-generally-faster-than-chrono","htmlText":"Jiff is generally faster than Chrono"},{"level":2,"text":"time (v0.3.36)","anchor":"time-v0336","htmlText":"time (v0.3.36)"},{"level":3,"text":"Time zone database integration","anchor":"time-zone-database-integration-1","htmlText":"Time zone database integration"},{"level":3,"text":"time supports its own custom format description","anchor":"time-supports-its-own-custom-format-description","htmlText":"time supports its own custom format description"},{"level":3,"text":"Jiff supports rounding datetimes","anchor":"jiff-supports-rounding-datetimes","htmlText":"Jiff supports rounding datetimes"},{"level":3,"text":"Jiff supports rounding durations","anchor":"jiff-supports-rounding-durations-1","htmlText":"Jiff supports rounding durations"},{"level":3,"text":"Jiff provides support for calendar arithmetic","anchor":"jiff-provides-support-for-calendar-arithmetic","htmlText":"Jiff provides support for calendar arithmetic"},{"level":3,"text":"Jiff supports conveniently re-balancing durations","anchor":"jiff-supports-conveniently-re-balancing-durations","htmlText":"Jiff supports conveniently re-balancing durations"},{"level":3,"text":"Jiff is generally faster than time","anchor":"jiff-is-generally-faster-than-time","htmlText":"Jiff is generally faster than time"},{"level":2,"text":"hifitime (v3.9.0)","anchor":"hifitime-v390","htmlText":"hifitime (v3.9.0)"},{"level":3,"text":"Time zone database integration","anchor":"time-zone-database-integration-2","htmlText":"Time zone database integration"},{"level":3,"text":"hifitime supports leap seconds","anchor":"hifitime-supports-leap-seconds","htmlText":"hifitime supports leap seconds"},{"level":3,"text":"Jiff makes checked or saturating arithmetic explicit","anchor":"jiff-makes-checked-or-saturating-arithmetic-explicit","htmlText":"Jiff makes checked or saturating arithmetic explicit"},{"level":2,"text":"icu (v1.5.0)","anchor":"icu-v150","htmlText":"icu (v1.5.0)"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eComparison with other Rust datetime crates\u003c/h1\u003e\u003ca id=\"user-content-comparison-with-other-rust-datetime-crates\" class=\"anchor\" aria-label=\"Permalink: Comparison with other Rust datetime crates\" href=\"#comparison-with-other-rust-datetime-crates\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis document is meant to be a comparison between Jiff and each of the other\nprominent open source datetime libraries for Rust. If you feel like there is a\nlibrary missing from this list, please file an issue about it. I would prefer\nto only add libraries to this list that are being used in production or have a\nsubstantial number of users.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe goal of this document is to be as \u003cem\u003edescriptive\u003c/em\u003e and \u003cem\u003esubstantively\ncomplete\u003c/em\u003e as possible. For example, \"Chrono has a better API design than Jiff\"\nwould be a pretty vague value judgment that someone could easily disagree with.\nBut, \"Chrono allows using a zone-aware datetime type that is \u003ccode\u003eCopy\u003c/code\u003e while Jiff\ndoes not\" would be a factual comparison that someone might use to \u003cem\u003esupport\u003c/em\u003e an\nopinion that Chrono's API design is better than Jiff's. In other words, this\ndocument should provide the \"facts of comparison\" but refrain from assigning\nvalue judgments.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn terms of completeness, it is probably not realistic to expect 100%\ncompletion here. We aren't hunting for Korok Seeds. Instead, this document\naims for \u003cem\u003esubstantive\u003c/em\u003e completion. That is, if there's a point of difference\nbetween Jiff and another library that would likely influence someone's decision\nof which library to use, and can be articulated descriptively, then it should\nprobably be in this document.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe current status of this document is that it is both \u003cem\u003eincomplete\u003c/em\u003e and\n\u003cem\u003ebiased\u003c/em\u003e. That is, this first draft was written by the author of Jiff without\nany input from other crate maintainers. (To other crate maintainers: I welcome\nfeedback. Even if it's just filing an issue.)\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eNote that this document contains many code snippets. They can be tested with\n\u003ccode\u003ecargo test --doc _documentation::comparison\u003c/code\u003e from the root of this repository.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ca href=\"https://docs.rs/chrono\" rel=\"nofollow\"\u003e\u003ccode\u003echrono\u003c/code\u003e\u003c/a\u003e (v0.4.38)\u003c/h2\u003e\u003ca id=\"user-content-chrono-v0438\" class=\"anchor\" aria-label=\"Permalink: chrono (v0.4.38)\" href=\"#chrono-v0438\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eChrono is a Rust datetime library that provides a time zone aware datetime\ntype.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor the following comparisons, a \u003ccode\u003eCargo.toml\u003c/code\u003e with the following dependencies\nshould be able to run any of the programs in this section:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"anyhow = \u0026quot;1.0.81\u0026quot;\nchrono = \u0026quot;0.4.38\u0026quot;\nchrono-tz = { version = \u0026quot;0.9.0\u0026quot;, features = [\u0026quot;serde\u0026quot;] }\njiff = { version = \u0026quot;0.2.0\u0026quot;, features = [\u0026quot;serde\u0026quot;] }\nserde = \u0026quot;1.0.203\u0026quot;\nserde_json = \u0026quot;1.0.117\u0026quot;\ntzfile = \u0026quot;0.1.3\u0026quot;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eanyhow\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.81\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003echrono\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.4.38\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003echrono-tz\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.9.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eserde\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003ejiff\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.2.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eserde\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003eserde\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.203\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003eserde_json\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.117\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003etzfile\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.1.3\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTime zone database integration\u003c/h3\u003e\u003ca id=\"user-content-time-zone-database-integration\" class=\"anchor\" aria-label=\"Permalink: Time zone database integration\" href=\"#time-zone-database-integration\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff gives you automatic integration with your copy of the Time Zone Database.\nOn Unix, it's usually found at \u003ccode\u003e/usr/share/zoneinfo\u003c/code\u003e. On Windows, since there\nis no canonical location, Jiff will depend on \u003ccode\u003ejiff-tzdb\u003c/code\u003e by default, which\nwill embed the entire database into your binary. Jiff hides these details from\nyou. For example, to convert a civil time into an absolute time in a particular\ntime zone:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::civil::date;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = date(2024, 6, 30).at(9, 46, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-06-30T09:46:00-04:00[America/New_York]\u0026quot;);\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e6\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e46\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-06-30T09:46:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor Chrono, one recommended option is to use the\n\u003ca href=\"https://docs.rs/chrono-tz\" rel=\"nofollow\"\u003e\u003ccode\u003echrono-tz\u003c/code\u003e\u003c/a\u003e crate:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::TimeZone;\nuse chrono_tz::America::New_York;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = New_York.with_ymd_and_hms(2024, 6, 30, 9, 46, 0)\n        .single()\n        .context(\u0026quot;invalid naive time\u0026quot;)?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-06-30 09:46:00 EDT\u0026quot;);\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eAmerica\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e6\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e46\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esingle\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid naive time\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-06-30 09:46:00 EDT\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003echrono-tz\u003c/code\u003e works by embedding an entire copy of the Time Zone Database into\nyour binary, where each time zone is represented as a Rust value that can be\nimported via \u003ccode\u003euse\u003c/code\u003e. A disadvantage of this approach is that you're reliant on\n\u003ccode\u003echrono-tz\u003c/code\u003e updates to get the most recent time zone information. An advantage\nof this approach is that you never need to worry about an end user's system\nstate. Another advantage is that this allows a \u003ccode\u003eTimeZone\u003c/code\u003e trait implementation\nto be \u003ccode\u003eCopy\u003c/code\u003e via a \u003ccode\u003e\u0026amp;Tz\u003c/code\u003e, and that in turn allows a \u003ccode\u003echrono::DateTime\u003c/code\u003e to be\n\u003ccode\u003eCopy\u003c/code\u003e. In contrast, in Jiff, a \u003ccode\u003eTimeZone\u003c/code\u003e is never \u003ccode\u003eCopy\u003c/code\u003e. Since a \u003ccode\u003eZoned\u003c/code\u003e\nembeds a \u003ccode\u003eTimeZone\u003c/code\u003e, a \u003ccode\u003eZoned\u003c/code\u003e is never \u003ccode\u003eCopy\u003c/code\u003e either.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAnother recommended option is the \u003ca href=\"https://docs.rs/tzfile\" rel=\"nofollow\"\u003e\u003ccode\u003etzfile\u003c/code\u003e\u003c/a\u003e crate.\nUnlike \u003ccode\u003echrono-tz\u003c/code\u003e, the \u003ccode\u003etzfile\u003c/code\u003e crate will try to read time zone data from\nyour system's copy of the Time Zone Database.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::TimeZone;\nuse tzfile::Tz;\n\n#[cfg(unix)]\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let tz = Tz::named(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt = (\u0026amp;tz).with_ymd_and_hms(2024, 6, 30, 9, 46, 0)\n        .single()\n        .context(\u0026quot;invalid naive time\u0026quot;)?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-06-30 09:46:00 EDT\u0026quot;);\n    Ok(())\n}\n\n// `tzfile` exposes a platform specific API, which means\n// users of the crate have to deal with platform differences\n// themselves.\n#[cfg(not(unix))]\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e tzfile\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-c1\"\u003e#\u003cspan class=\"pl-kos\"\u003e[\u003c/span\u003ecfg\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eunix\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e]\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e tz = \u003cspan class=\"pl-smi\"\u003eTz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enamed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003etz\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e6\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e46\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esingle\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid naive time\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-06-30 09:46:00 EDT\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"pl-c\"\u003e// `tzfile` exposes a platform specific API, which means\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// users of the crate have to deal with platform differences\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// themselves.\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e#\u003cspan class=\"pl-kos\"\u003e[\u003c/span\u003ecfg\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003enot\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eunix\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e]\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNote though that at time of writing (2024-07-11), \u003ccode\u003etzfile::Tz::named\u003c/code\u003e will\nread and parse the corresponding time zone rules from disk on every call.\nConversely, in Jiff, all time zone lookups by name are cached. This may or may\nnot matter for your use case.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff losslessly roundtrips time zone aware datetimes\u003c/h3\u003e\u003ca id=\"user-content-jiff-losslessly-roundtrips-time-zone-aware-datetimes\" class=\"anchor\" aria-label=\"Permalink: Jiff losslessly roundtrips time zone aware datetimes\" href=\"#jiff-losslessly-roundtrips-time-zone-aware-datetimes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn Jiff, with \u003ccode\u003eserde\u003c/code\u003e support enabled, one can serialize and deserialize a\n\u003ccode\u003eZoned\u003c/code\u003e value losslessly. This means that, after deserialization, you can\nexpect it to still perform DST arithmetic:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, ToSpan, Zoned};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = date(2024, 3, 10).at(1, 59, 59, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n\n    let json = serde_json::to_string_pretty(\u0026amp;zdt)?;\n    assert_eq!(json, \u0026quot;\\\u0026quot;2024-03-10T01:59:59-05:00[America/New_York]\\\u0026quot;\u0026quot;);\n\n    let got: Zoned = serde_json::from_str(\u0026amp;json)?;\n    assert_eq!(got.to_string(), \u0026quot;2024-03-10T01:59:59-05:00[America/New_York]\u0026quot;);\n    let next = got.checked_add(1.minute())?;\n    assert_eq!(next.to_string(), \u0026quot;2024-03-10T03:00:59-04:00[America/New_York]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eZoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e json = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_string_pretty\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e2024-03-10T01:59:59-05:00[America/New_York]\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e got\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eZoned\u003c/span\u003e = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_str\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003egot\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10T01:59:59-05:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e next = got\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003enext\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10T03:00:59-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNotice that when we add a minute, it jumps to \u003ccode\u003e03:00\u003c/code\u003e civil time because of the\ntransition into daylight saving time in my selected time zone. Notice also the\noffset change from \u003ccode\u003e-05\u003c/code\u003e to \u003ccode\u003e-04\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eCompare this with Chrono which also supports \u003ccode\u003eserde\u003c/code\u003e, but not with \u003ccode\u003echrono-tz\u003c/code\u003e\nor \u003ccode\u003etzfile\u003c/code\u003e. One option is to use its \u003ccode\u003eLocal\u003c/code\u003e implementation of its \u003ccode\u003eTimeZone\u003c/code\u003e\ntrait:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::{DateTime, FixedOffset, Local, TimeDelta, TimeZone};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = Local.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)\n        .single()\n        .context(\u0026quot;invalid naive time\u0026quot;)?;\n\n    let json = serde_json::to_string_pretty(\u0026amp;zdt)?;\n    // Chrono only serializes the offset, which makes lossless\n    // deserialization impossible. Chrono loses the time zone\n    // information.\n    assert_eq!(json, \u0026quot;\\\u0026quot;2024-03-10T01:59:59-05:00\\\u0026quot;\u0026quot;);\n\n    // The serialized datetime has no time zone information,\n    // so unless there is some out-of-band information saying\n    // what its time zone is, we're forced to use a fixed offset:\n    let got: DateTime\u0026lt;FixedOffset\u0026gt; = serde_json::from_str(\u0026amp;json)?;\n    assert_eq!(got.to_string(), \u0026quot;2024-03-10 01:59:59 -05:00\u0026quot;);\n    let next = got.checked_add_signed(TimeDelta::minutes(1))\n        .context(\u0026quot;arithmetic failed\u0026quot;)?;\n    // This is correct for fixed offset, but it's no longer\n    // DST aware.\n    assert_eq!(next.to_string(), \u0026quot;2024-03-10 02:00:59 -05:00\u0026quot;);\n\n    // We could deserialize into a `DateTime\u0026lt;Local\u0026gt;`, but this\n    // requires knowing that the time zone of the datetime matches\n    // local time zone. Which you might know. But you might not.\n    let got: DateTime\u0026lt;Local\u0026gt; = serde_json::from_str(\u0026amp;json)?;\n    assert_eq!(got.to_string(), \u0026quot;2024-03-10 01:59:59 -05:00\u0026quot;);\n    let next = got.checked_add_signed(TimeDelta::minutes(1))\n        .context(\u0026quot;arithmetic failed\u0026quot;)?;\n    assert_eq!(next.to_string(), \u0026quot;2024-03-10 03:00:59 -04:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eFixedOffset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eLocal\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-v\"\u003eLocal\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esingle\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid naive time\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e json = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_string_pretty\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Chrono only serializes the offset, which makes lossless\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// deserialization impossible. Chrono loses the time zone\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// information.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e2024-03-10T01:59:59-05:00\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// The serialized datetime has no time zone information,\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// so unless there is some out-of-band information saying\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// what its time zone is, we're forced to use a fixed offset:\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e got\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eFixedOffset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_str\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003egot\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 01:59:59 -05:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e next = got\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add_signed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"arithmetic failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// This is correct for fixed offset, but it's no longer\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// DST aware.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003enext\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 02:00:59 -05:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// We could deserialize into a `DateTime\u0026lt;Local\u0026gt;`, but this\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// requires knowing that the time zone of the datetime matches\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// local time zone. Which you might know. But you might not.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e got\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eLocal\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_str\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003egot\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 01:59:59 -05:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e next = got\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add_signed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"arithmetic failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003enext\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 03:00:59 -04:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOr, if you have a \u003ccode\u003eTz\u003c/code\u003e from \u003ccode\u003echrono-tz\u003c/code\u003e. But in this case, since \u003ccode\u003echrono-tz\u003c/code\u003e\ndoesn't support Serde, you have to convert to a \u003ccode\u003eDateTime\u0026lt;FixedOffset\u0026gt;\u003c/code\u003e. Like\nabove, you'll lose DST safe arithmetic after deserialization:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::{DateTime, FixedOffset, TimeDelta, TimeZone};\nuse chrono_tz::America::New_York;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = New_York.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)\n        .single()\n        .context(\u0026quot;invalid naive time\u0026quot;)?;\n\n    let json = serde_json::to_string_pretty(\u0026amp;zdt.fixed_offset())?;\n    // Chrono only serializes the offset, which makes lossless\n    // deserialization impossible. Chrono loses the time zone\n    // information.\n    assert_eq!(json, \u0026quot;\\\u0026quot;2024-03-10T01:59:59-05:00\\\u0026quot;\u0026quot;);\n\n    // The serialized datetime has no time zone information,\n    // so unless there is some out-of-band information saying\n    // what its time zone is, we're forced to use a fixed offset:\n    let got: DateTime\u0026lt;FixedOffset\u0026gt; = serde_json::from_str(\u0026amp;json)?;\n    assert_eq!(got.to_string(), \u0026quot;2024-03-10 01:59:59 -05:00\u0026quot;);\n    let next = got.checked_add_signed(TimeDelta::minutes(1))\n        .context(\u0026quot;arithmetic failed\u0026quot;)?;\n    // This is correct for fixed offset, but it's no longer\n    // DST aware.\n    assert_eq!(next.to_string(), \u0026quot;2024-03-10 02:00:59 -05:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eFixedOffset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eAmerica\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esingle\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid naive time\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e json = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_string_pretty\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efixed_offset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Chrono only serializes the offset, which makes lossless\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// deserialization impossible. Chrono loses the time zone\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// information.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e2024-03-10T01:59:59-05:00\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// The serialized datetime has no time zone information,\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// so unless there is some out-of-band information saying\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// what its time zone is, we're forced to use a fixed offset:\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e got\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eFixedOffset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_str\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003egot\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 01:59:59 -05:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e next = got\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add_signed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"arithmetic failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// This is correct for fixed offset, but it's no longer\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// DST aware.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003enext\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 02:00:59 -05:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe main way to solve this problem (and is how \u003ccode\u003ejava.time\u003c/code\u003e, Temporal and Jiff\nsolve it), is by supporting \u003ca href=\"https://datatracker.ietf.org/doc/rfc9557/\" rel=\"nofollow\"\u003eRFC 9557\u003c/a\u003e. Otherwise, the only way to fully\ncapture Jiff's functionality in Chrono is to define a custom serialization\nformat that includes the instant, the time zone identifier \u003cem\u003eand\u003c/em\u003e the offset.\n(The offset is used for conflict resolution when deserializing datetimes made\nin the future for which their offset has changed due to changes in the time\nzone database.)\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff provides support for zone aware calendar arithmetic\u003c/h3\u003e\u003ca id=\"user-content-jiff-provides-support-for-zone-aware-calendar-arithmetic\" class=\"anchor\" aria-label=\"Permalink: Jiff provides support for zone aware calendar arithmetic\" href=\"#jiff-provides-support-for-zone-aware-calendar-arithmetic\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWith Jiff, you can add non-uniform units like days to time zone aware datetimes,\nand get non-uniform units like days as a representation of a span between\ndatetimes. And they agree on the results.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, ToSpan, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = zdt1.checked_add(1.day())?;\n\n    // Even though 2 o'clock didn't occur on 2024-03-10, adding 1 day\n    // returns the same civil time the next day.\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-03-10T21:00:00-04:00[America/New_York]\u0026quot;);\n    // The span of time is 23 hours:\n    assert_eq!(\u0026amp;zdt2 - \u0026amp;zdt1, 23.hours().fieldwise());\n    // But if you ask for the span in units of days, you get exactly 1:\n    assert_eq!(zdt1.until((Unit::Day, \u0026amp;zdt2))?, 1.day().fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// Even though 2 o'clock didn't occur on 2024-03-10, adding 1 day\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// returns the same civil time the next day.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10T21:00:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// The span of time is 23 hours:\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt2 - \u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt1\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e23\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// But if you ask for the span in units of days, you get exactly 1:\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003euntil\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eday\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis is important and difficult to get right because some days are only 23\nhours long (typically the day of the year where DST starts) and some days are\n25 hours long (typically the day of the year where DST ends). With Jiff, you\ncan seamlessly go back-and-forth between calendar units and clock units without\nworrying about whether \"day\" will be interpreted differently.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eChrono has some support for this. Namely, it can add units of days in a time\nzone aware fashion, but it cannot produce spans of time involving days between\ntwo zone aware datetimes that is consistent with adding days.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::{Days, TimeDelta, TimeZone};\nuse chrono_tz::America::New_York;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = New_York.with_ymd_and_hms(2024, 3, 9, 21, 0, 0)\n        .single()\n        .context(\u0026quot;invalid naive time\u0026quot;)?;\n\n    // Adding 1 day via TimeDelta leads to a result that is\n    // 24 hours later, including the gap at 2am on 2024-03-10.\n    // As a result, you get a different civil time, which is\n    // usually not what is intended.\n    let zdt2 = zdt1.checked_add_signed(TimeDelta::days(1))\n        .context(\u0026quot;adding a time delta failed\u0026quot;)?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-03-10 22:00:00 EDT\u0026quot;);\n\n    // However, Chrono does expose a separate API for adding\n    // units of days specifically. This does get you the\n    // correct result.\n    let zdt2 = zdt1.checked_add_days(Days::new(1))\n        .context(\u0026quot;adding days failed\u0026quot;)?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-03-10 21:00:00 EDT\u0026quot;);\n\n    // The only way to compute a duration between two datetimes\n    // in Chrono is with a `TimeDelta`:\n    let delta = zdt2.signed_duration_since(\u0026amp;zdt1);\n    // And since `TimeDelta` assumes all days are exactly 24\n    // hours long, you get a result of `0` days. If this were\n    // a fold, the number of days would be `1`, but you'd also\n    // have a number of hours equal to `1`.\n    assert_eq!(delta.num_days(), 0);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eAmerica\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esingle\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid naive time\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// Adding 1 day via TimeDelta leads to a result that is\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// 24 hours later, including the gap at 2am on 2024-03-10.\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// As a result, you get a different civil time, which is\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// usually not what is intended.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add_signed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eTimeDelta\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"adding a time delta failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 22:00:00 EDT\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// However, Chrono does expose a separate API for adding\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// units of days specifically. This does get you the\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// correct result.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add_days\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eDays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"adding days failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 21:00:00 EDT\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// The only way to compute a duration between two datetimes\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// in Chrono is with a `TimeDelta`:\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e delta = zdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esigned_duration_since\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt1\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// And since `TimeDelta` assumes all days are exactly 24\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// hours long, you get a result of `0` days. If this were\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// a fold, the number of days would be `1`, but you'd also\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// have a number of hours equal to `1`.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003edelta\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003enum_days\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff losslessly roundtrips durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-losslessly-roundtrips-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff losslessly roundtrips durations\" href=\"#jiff-losslessly-roundtrips-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff implements something close to ISO 8601 to provide lossless serialization\nand deserialization of its \u003ccode\u003eSpan\u003c/code\u003e type. A \u003ccode\u003eSpan\u003c/code\u003e covers both calendar and clock\nunits.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{Span, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let span = 5.years().months(2).days(1).hours(20);\n    let json = serde_json::to_string_pretty(\u0026amp;span)?;\n    assert_eq!(json, \u0026quot;\\\u0026quot;P5Y2M1DT20H\\\u0026quot;\u0026quot;);\n\n    let got: Span = serde_json::from_str(\u0026amp;json)?;\n    assert_eq!(got, span.fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = \u003cspan class=\"pl-c1\"\u003e5\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eyears\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emonths\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e json = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_string_pretty\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003eP5Y2M1DT20H\u003cspan class=\"pl-cce\"\u003e\\\"\u003c/span\u003e\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e got\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eSpan\u003c/span\u003e = serde_json\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_str\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ejson\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003egot\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e span\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eChrono \u003ca href=\"https://github.com/chronotope/chrono/issues/117\" data-hovercard-type=\"issue\" data-hovercard-url=\"/chronotope/chrono/issues/117/hovercard\"\u003edoes not currently have Serde support for its duration type\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports dealing with gaps in civil time\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-dealing-with-gaps-in-civil-time\" class=\"anchor\" aria-label=\"Permalink: Jiff supports dealing with gaps in civil time\" href=\"#jiff-supports-dealing-with-gaps-in-civil-time\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA gap in civil time most typically occurs when a particular region enters\ndaylight saving time. When this happens, some time on the clocks in that region\nis skipped. It never appears. (A fold happens when the clocks are rolled back,\nusually when leaving daylight saving time. In this case, some time on the clock\nis repeated.)\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eJiff supports automatically selecting a \"reasonable\" choice in either case\nvia its \"compatible\" strategy (as specified by \u003ca href=\"https://datatracker.ietf.org/doc/html/rfc5545\" rel=\"nofollow\"\u003eRFC 5545\u003c/a\u003e).\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::Zoned;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // This is a gap. The default strategy takes the time after the gap.\n    let zdt: Zoned = \u0026quot;2024-03-10 02:30[America/New_York]\u0026quot;.parse()?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-03-10T03:30:00-04:00[America/New_York]\u0026quot;);\n\n    // This is a fold. The default strategy takes the time before the fold.\n    let zdt: Zoned = \u0026quot;2024-11-03 01:30[America/New_York]\u0026quot;.parse()?;\n    // The time after the fold would be identical,\n    // except the offset would be -05.\n    assert_eq!(zdt.to_string(), \u0026quot;2024-11-03T01:30:00-04:00[America/New_York]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eZoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// This is a gap. The default strategy takes the time after the gap.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eZoned\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2024-03-10 02:30[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10T03:30:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// This is a fold. The default strategy takes the time before the fold.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eZoned\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2024-11-03 01:30[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// The time after the fold would be identical,\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// except the offset would be -05.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-11-03T01:30:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff also exposes all information available with respect to ambiguous civil\ndatetimes via \u003ccode\u003etz::AmbiguousZoned\u003c/code\u003e, \u003ccode\u003etz::AmbiguousTimestamp\u003c/code\u003e and\n\u003ccode\u003etz::AmbiguousOffset\u003c/code\u003e. This enables callers to implement whatever strategy\nthey want.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhile Chrono will let you deal with folds, it returns \u003ccode\u003eMappedLocalTime::None\u003c/code\u003e\nin the case of a gap with no additional information. So there's really nothing\nelse you can conveniently do in this case except return an error:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse chrono::{offset::MappedLocalTime, TimeZone};\nuse chrono_tz::America::New_York;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // For gaps, Chrono exposes no additional information.\n    let mapped = New_York.with_ymd_and_hms(2024, 3, 10, 2, 30, 0);\n    assert_eq!(mapped, MappedLocalTime::None);\n\n    // For folds, Chrono gives you the two choices.\n    // This is approximately equivalent to what Jiff exposes\n    // in the case of a fold.\n    let zdt = New_York.with_ymd_and_hms(2024, 11, 3, 1, 30, 0)\n        .earliest()\n        .context(\u0026quot;invalid datetime\u0026quot;)?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-11-03 01:30:00 EDT\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003eoffset\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eMappedLocalTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e chrono_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eAmerica\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// For gaps, Chrono exposes no additional information.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e mapped = \u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003emapped\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eMappedLocalTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// For folds, Chrono gives you the two choices.\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// This is approximately equivalent to what Jiff exposes\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// in the case of a fold.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-v\"\u003eNew_York\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ewith_ymd_and_hms\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eearliest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"invalid datetime\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-11-03 01:30:00 EDT\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports rounding durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-rounding-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff supports rounding durations\" href=\"#jiff-supports-rounding-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn Jiff, one can round the duration computed between two datetimes:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n\n    let round_options = ZonedDifference::new(\u0026amp;zdt2)\n        .largest(Unit::Year)\n        .smallest(Unit::Day)\n        .mode(RoundMode::HalfExpand);\n    let span = zdt1.until(round_options)?;\n    assert_eq!(span.fieldwise(), 22.years().months(7).days(24));\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2001\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e8\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e38\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e round_options = \u003cspan class=\"pl-smi\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eYear\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esmallest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHalfExpand\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003euntil\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eround_options\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eyears\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003emonths\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003edays\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhile Chrono supports rounding datetimes themselves via its\n\u003ccode\u003echrono::duration::DurationRound\u003c/code\u003e trait, it does not support rounding durations\nthemselves. Indeed, its principle duration type, \u003ccode\u003eTimeDelta\u003c/code\u003e, is an \"absolute\"\nduration like \u003ccode\u003estd::time::Duration\u003c/code\u003e (except that it is signed). It doesn't keep\ntrack of individual units like Jiff does. Instead, everything gets normalized\ninto a 96-bit integer number of nanoseconds. With this representation, it is\nimpossible to do DST safe rounding to non-uniform units like days.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports zone-aware rounding of durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-zone-aware-rounding-of-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff supports zone-aware rounding of durations\" href=\"#jiff-supports-zone-aware-rounding-of-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff's duration rounding is time zone aware. For example, if you're rounding to\na number of days, it knows to round 11.5 hours up to 1 day on days with gaps,\nand round 12 hours down to 0 days on days with folds. The only requirement\nis that we provide a reference datetime with which to interpret the span.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, SpanRound, ToSpan, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let gapday = date(2024, 3, 10).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let foldday = date(2024, 11, 3).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n\n    let span1 = 11.hours().minutes(30);\n    let span2 = span1.round(\n        SpanRound::new().smallest(Unit::Day).relative(\u0026amp;gapday),\n    )?;\n    // rounds up, even though on a normal day 11.5 hours would round down.\n    assert_eq!(span2, 1.day().fieldwise());\n\n    let span1 = 12.hours();\n    let span2 = span1.round(\n        SpanRound::new().smallest(Unit::Day).relative(\u0026amp;foldday),\n    )?;\n    // rounds down, even though on a normal day 12 hours would round up.\n    assert_eq!(span2, 0.days().fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e gapday = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e foldday = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esmallest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003erelative\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003egapday\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// rounds up, even though on a normal day 11.5 hours would round down.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eday\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e12\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esmallest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003erelative\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003efoldday\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// rounds down, even though on a normal day 12 hours would round up.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003edays\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAs with the previous section, Chrono does not support rounding durations or\nrounding units like \u003ccode\u003eDays\u003c/code\u003e with respect to a reference datetime.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports re-balancing durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-re-balancing-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff supports re-balancing durations\" href=\"#jiff-supports-re-balancing-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis example is like the one above, except we choose a smaller \"largest\" unit:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n\n    let round_options = ZonedDifference::new(\u0026amp;zdt2)\n        .largest(Unit::Month)\n        .smallest(Unit::Day)\n        .mode(RoundMode::HalfExpand);\n    let span = zdt1.until(round_options)?;\n    assert_eq!(span, 271.months().days(24).fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2001\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e8\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e38\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e round_options = \u003cspan class=\"pl-smi\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eMonth\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esmallest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHalfExpand\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003euntil\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eround_options\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e271\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003emonths\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003edays\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports getting the \u003ccode\u003enth\u003c/code\u003e weekday from the current date\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-getting-the-nth-weekday-from-the-current-date\" class=\"anchor\" aria-label=\"Permalink: Jiff supports getting the nth weekday from the current date\" href=\"#jiff-supports-getting-the-nth-weekday-from-the-current-date\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::civil::{date, Weekday};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = date(2024, 7, 11).at(22, 59, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    assert_eq!(zdt.weekday(), Weekday::Thursday);\n\n    let next_tuesday = zdt.nth_weekday(1, Weekday::Tuesday)?;\n    assert_eq!(\n        next_tuesday.to_string(),\n        \u0026quot;2024-07-16T22:59:00-04:00[America/New_York]\u0026quot;,\n    );\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eWeekday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eweekday\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eWeekday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eThursday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e next_tuesday = zdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enth_weekday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eWeekday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTuesday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        next_tuesday\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n        \u003cspan class=\"pl-s\"\u003e\"2024-07-16T22:59:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eChrono does have \u003ccode\u003eNaiveDate::from_weekday_of_month_opt\u003c/code\u003e, but it only counts\nthe number of weekdays for a particular month. (The Jiff equivalent is\n\u003ccode\u003enth_weekday_of_month\u003c/code\u003e.) Moreover, Chrono's method is only available on naive\ndates and not zone aware datetimes.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports detecting time zone offset conflicts\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-detecting-time-zone-offset-conflicts\" class=\"anchor\" aria-label=\"Permalink: Jiff supports detecting time zone offset conflicts\" href=\"#jiff-supports-detecting-time-zone-offset-conflicts\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOne of the problems with storing datetimes in the future is that time\nzone rules can change. For example, if you stored the zone aware datetime\n\u003ccode\u003e2020-01-15T12:00-02[America/Sao_Paulo]\u003c/code\u003e in 2018, then it would be considered\nto be in daylight saving time with an offset of \u003ccode\u003e-2\u003c/code\u003e. However, in 2019,\ndaylight saving time was abolished in this time zone, which renders the\ndatetime invalid because its offset \u003cem\u003eshould\u003c/em\u003e be \u003ccode\u003e-3\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eJiff can detect these sorts of conflicts and will actually return a parse error\nby default. We exemplify this by creating and serializing a zoned datetime from\nan old copy of the Time Zone Database, and then try to parse it back using our\nsystem's current copy of the Time Zone Database. (This also demonstrate's Jiff\nsupport for using multiple copies of the Time Zone Database simultaneously.\nBut the main point here is to simulate the process of \"serialize datetime,\ntime zone rules change, deserialize datetime.\")\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{fmt::temporal::DateTimeParser, tz::{self, TimeZoneDatabase}};\n\n// We use a custom parser with a default configuration because we need\n// to ask the parser to use a different time zone database than the\n// default. This can't be done via the nice `\u0026quot;...\u0026quot;.parse()` API one\n// would typically use.\nstatic PARSER: DateTimeParser = DateTimeParser::new();\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // Open a version of tzdb from before Brazil announced its abolition\n    // of daylight saving time.\n    let tzdb2018 = TimeZoneDatabase::from_dir(\u0026quot;path/to/tzdb-2018b\u0026quot;)?;\n    // Open the system tzdb.\n    let tzdb = tz::db();\n\n    // Parse the same datetime string with the same parser, but using two\n    // different versions of tzdb.\n    let dt = \u0026quot;2020-01-15T12:00[America/Sao_Paulo]\u0026quot;;\n    let zdt2018 = PARSER.parse_zoned_with(\u0026amp;tzdb2018, dt)?;\n    let zdt = PARSER.parse_zoned_with(tzdb, dt)?;\n\n    // Before DST was abolished, 2020-01-15 was in DST, which corresponded\n    // to UTC offset -02. Since DST rules applied to datetimes in the\n    // future, the 2018 version of tzdb would lead one to interpret\n    // 2020-01-15 as being in DST.\n    assert_eq!(zdt2018.offset(), tz::offset(-2));\n    // But DST was abolished in 2019, which means that 2020-01-15 was no\n    // no longer in DST. So after a tzdb update, the same datetime as above\n    // now has a different offset.\n    assert_eq!(zdt.offset(), tz::offset(-3));\n\n    // So if you try to parse a datetime serialized from an older copy of\n    // tzdb with a new copy of tzdb, you'll get an error under the default\n    // configuration because of `OffsetConflict::Reject`. This would succeed if\n    // you parsed it using tzdb2018!\n    assert!(PARSER.parse_zoned_with(tzdb, zdt2018.to_string()).is_err());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003efmt\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003etemporal\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDateTimeParser\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eself\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZoneDatabase\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-c\"\u003e// We use a custom parser with a default configuration because we need\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// to ask the parser to use a different time zone database than the\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// default. This can't be done via the nice `\"...\".parse()` API one\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e// would typically use.\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003estatic\u003c/span\u003e \u003cspan class=\"pl-v\"\u003ePARSER\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eDateTimeParser\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eDateTimeParser\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Open a version of tzdb from before Brazil announced its abolition\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// of daylight saving time.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e tzdb2018 = \u003cspan class=\"pl-smi\"\u003eTimeZoneDatabase\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_dir\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"path/to/tzdb-2018b\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Open the system tzdb.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e tzdb = tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edb\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// Parse the same datetime string with the same parser, but using two\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// different versions of tzdb.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e dt = \u003cspan class=\"pl-s\"\u003e\"2020-01-15T12:00[America/Sao_Paulo]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2018 = \u003cspan class=\"pl-v\"\u003ePARSER\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse_zoned_with\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003etzdb2018\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e dt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-v\"\u003ePARSER\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse_zoned_with\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003etzdb\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e dt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// Before DST was abolished, 2020-01-15 was in DST, which corresponded\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// to UTC offset -02. Since DST rules applied to datetimes in the\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// future, the 2018 version of tzdb would lead one to interpret\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// 2020-01-15 as being in DST.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2018\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eoffset\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eoffset\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// But DST was abolished in 2019, which means that 2020-01-15 was no\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// no longer in DST. So after a tzdb update, the same datetime as above\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// now has a different offset.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eoffset\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eoffset\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// So if you try to parse a datetime serialized from an older copy of\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// tzdb with a new copy of tzdb, you'll get an error under the default\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// configuration because of `OffsetConflict::Reject`. This would succeed if\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// you parsed it using tzdb2018!\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-v\"\u003ePARSER\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eparse_zoned_with\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003etzdb\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e zdt2018\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eis_err\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWith Chrono, this sort of checking isn't possible in the first place because\nit doesn't support an interchange format that includes the IANA time zone\nidentifier.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports adding durations with calendar units\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-adding-durations-with-calendar-units\" class=\"anchor\" aria-label=\"Permalink: Jiff supports adding durations with calendar units\" href=\"#jiff-supports-adding-durations-with-calendar-units\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSince \u003ccode\u003eSpan\u003c/code\u003e is Jiff's single duration type that combines calendar and clock\nunits, one can freely add them together. The only requirement is that if a span\nhas calendar units, you need to provide a reference date. (Because 1 month from\nApril 1 is shorter than 1 month from May 1.)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let span1 = 2.years().months(4).days(25).hours(23);\n    let span2 = 3.hours();\n    let span3 = span1.checked_add((span2, date(2024, 1, 1)))?;\n    assert_eq!(span3.fieldwise(), 2.years().months(4).days(26).hours(2));\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eyears\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emonths\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e25\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e23\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span3 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan3\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eyears\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003emonths\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003edays\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e26\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhile Chrono has types like \u003ccode\u003eMonths\u003c/code\u003e and \u003ccode\u003eDays\u003c/code\u003e, there's no way to combine\nthem into one, and Chrono does not provide operations on both at the same time.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports zone-aware re-balancing of durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-zone-aware-re-balancing-of-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff supports zone-aware re-balancing of durations\" href=\"#jiff-supports-zone-aware-re-balancing-of-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you have a span of \u003ccode\u003e1.day()\u003c/code\u003e and want to convert it to hours, then that\ncalculation depends on how long the day is. If you provide a civil date as\na relative reference point, then Jiff assumes the day is always 24 hours long:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil, SpanRound, ToSpan, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let relative = civil::date(2024, 4, 1);\n    let span1 = 1.day();\n    let span2 = span1.round(\n        SpanRound::new().largest(Unit::Hour).relative(relative),\n    )?;\n    assert_eq!(span2, 24.hours().fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e relative = civil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003erelative\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003erelative\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBut if a reference date is provided with a time zone, then the re-balancing is\nDST safe:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, SpanRound, ToSpan, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // In the case of a gap (typically transitioning in DST):\n    let zdt = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let span1 = 1.day();\n    let span2 = span1.round(\n        SpanRound::new().largest(Unit::Hour).relative(\u0026amp;zdt)\n    )?;\n    assert_eq!(span2, 23.hours().fieldwise());\n\n    // In the case of a fold (typically transitioning out of DST):\n    let zdt = date(2024, 11, 2).at(21, 0, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let span1 = 1.day();\n    let span2 = span1.round(\n        SpanRound::new().largest(Unit::Hour).relative(\u0026amp;zdt)\n    )?;\n    assert_eq!(span2, 25.hours().fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// In the case of a gap (typically transitioning in DST):\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e9\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003erelative\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e23\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// In the case of a fold (typically transitioning out of DST):\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eday\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003erelative\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e25\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff is generally faster than Chrono\u003c/h3\u003e\u003ca id=\"user-content-jiff-is-generally-faster-than-chrono\" class=\"anchor\" aria-label=\"Permalink: Jiff is generally faster than Chrono\" href=\"#jiff-is-generally-faster-than-chrono\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThere are some cases where Chrono is faster than Jiff, but Jiff should\ngenerally be competitive for equivalent operations. It's generally not\npossible for Chrono or Jiff to always be faster than the other, since\nthey each use different representations for fundamental types. This in turn\nmakes some operations faster and others slower, depending on what you're\ntrying to do. With that said, Jiff is uniformly faster than Chrono when it\ncomes to printing and parsing.\u003c/p\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"$ cd bench\n$ cargo bench -- --save-baseline base\n[.. snip ..]\n$ critcmp base -g '(.*)/(?:jiff|chrono)$'\ngroup                                                           baseline//chrono                       baseline//jiff\n-----                                                           ----------------                       --------------\ncivil_datetime/add_days/diffyear/duration                       1.00      8.5±0.08ns        ? ?/sec    1.56     13.3±0.15ns        ? ?/sec\ncivil_datetime/add_days/diffyear/span                                                                  1.00     23.9±0.13ns        ? ?/sec\ncivil_datetime/add_days/sameyear/duration                       1.00      6.8±0.05ns        ? ?/sec    1.96     13.3±0.17ns        ? ?/sec\ncivil_datetime/add_days/sameyear/span                                                                  1.00     23.8±0.13ns        ? ?/sec\ncivil_datetime/to_timestamp_static/bundled                      2.05     22.3±0.24ns        ? ?/sec    1.00     10.9±0.14ns        ? ?/sec\ncivil_datetime/to_timestamp_static/zoneinfo                     1.53     16.2±0.15ns        ? ?/sec    1.00     10.6±0.09ns        ? ?/sec\ncivil_datetime/to_timestamp_tzdb_lookup/bundled                 1.00     32.0±0.15ns        ? ?/sec\ncivil_datetime/to_timestamp_tzdb_lookup/zoneinfo                45.85  1919.7±6.17ns        ? ?/sec    1.00     41.9±0.15ns        ? ?/sec\ndate/add_days/diffyear/duration                                 1.00      5.8±0.05ns        ? ?/sec    1.12      6.5±0.04ns        ? ?/sec\ndate/add_days/diffyear/span                                                                            1.00      6.5±0.04ns        ? ?/sec\ndate/add_days/one/duration                                      1.00      2.1±0.02ns        ? ?/sec    2.55      5.4±0.05ns        ? ?/sec\ndate/add_days/one/span                                                                                 1.00      5.8±0.02ns        ? ?/sec\ndate/add_days/sameyear/duration                                 1.00      2.1±0.01ns        ? ?/sec    3.08      6.5±0.05ns        ? ?/sec\ndate/add_days/sameyear/span                                                                            1.00      6.5±0.05ns        ? ?/sec\ndate/difference_days/duration                                   1.18      3.4±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec\ndate/difference_days/span                                                                              1.00      2.5±0.02ns        ? ?/sec\ndate/tomorrow/diff-month                                        1.00      0.4±0.00ns        ? ?/sec    3.25      1.3±0.01ns        ? ?/sec\ndate/tomorrow/diff-year                                         1.16      1.7±0.01ns        ? ?/sec    1.00      1.4±0.01ns        ? ?/sec\ndate/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec    1.99      0.8±0.00ns        ? ?/sec\ndate/yesterday/diff-month                                       1.00      0.4±0.02ns        ? ?/sec    3.17      1.3±0.01ns        ? ?/sec\ndate/yesterday/diff-year                                        1.85      2.0±0.01ns        ? ?/sec    1.00      1.1±0.01ns        ? ?/sec\ndate/yesterday/same-month                                       1.00      0.4±0.03ns        ? ?/sec    1.72      0.7±0.02ns        ? ?/sec\nparse/civil_datetime                                            2.95     73.6±0.72ns        ? ?/sec    1.00     24.9±0.19ns        ? ?/sec\nparse/rfc2822                                                   3.09     59.9±0.30ns        ? ?/sec    1.00     19.3±0.17ns        ? ?/sec\nparse/strptime/oneshot                                          3.11    197.8±0.80ns        ? ?/sec    1.00     63.6±1.19ns        ? ?/sec\nparse/strptime/prebuilt                                         1.00     77.1±1.44ns        ? ?/sec\nprint/civil_datetime                                            13.10   147.4±0.60ns        ? ?/sec    1.00     11.3±0.04ns        ? ?/sec\nprint/iso8601_duration/long-time/duration/buffer                2.38     46.5±0.34ns        ? ?/sec    1.00     19.5±0.04ns        ? ?/sec\nprint/iso8601_duration/long-time/duration/to_string             3.13     71.7±0.36ns        ? ?/sec    1.00     23.0±0.07ns        ? ?/sec\nprint/iso8601_duration/short/duration/buffer                    2.65     32.3±0.30ns        ? ?/sec    1.00     12.2±0.04ns        ? ?/sec\nprint/iso8601_duration/short/duration/to_string                 2.08     36.8±0.33ns        ? ?/sec    1.00     17.7±0.05ns        ? ?/sec\nprint/iso8601_duration/tiny/duration/buffer                     2.74     31.6±0.32ns        ? ?/sec    1.00     11.6±0.03ns        ? ?/sec\nprint/iso8601_duration/tiny/duration/to_string                  2.28     36.5±0.40ns        ? ?/sec    1.00     16.0±0.08ns        ? ?/sec\nprint/rfc2822/buffer                                            4.91     64.6±0.59ns        ? ?/sec    1.00     13.2±0.03ns        ? ?/sec\nprint/rfc2822/to_string                                         5.75    111.0±0.37ns        ? ?/sec    1.00     19.3±0.05ns        ? ?/sec\nprint/rfc3339/buffer                                            3.79     64.2±0.56ns        ? ?/sec    1.00     17.0±0.14ns        ? ?/sec\nprint/rfc3339/to_string                                         4.75    112.4±0.33ns        ? ?/sec    1.00     23.6±0.11ns        ? ?/sec\nprint/rfc9557/buffer                                                                                   1.00     16.2±0.05ns        ? ?/sec\nprint/rfc9557/to_string                                                                                1.00     22.2±0.07ns        ? ?/sec\nprint/strftime/oneshot/buffer                                   3.90    213.9±1.99ns        ? ?/sec    1.00     54.8±0.32ns        ? ?/sec\nprint/strftime/oneshot/to_string                                3.63    261.3±1.26ns        ? ?/sec    1.00     72.1±0.49ns        ? ?/sec\nprint/strftime/oneshot/zoned                                                                           1.00     65.5±0.64ns        ? ?/sec\nprint/strftime/prebuilt/buffer                                  1.00     85.4±0.52ns        ? ?/sec\nprint/strftime/prebuilt/to_string                               1.00    147.4±0.76ns        ? ?/sec\ntimestamp/add_time_secs/duration                                2.42      6.1±0.08ns        ? ?/sec    1.00      2.5±0.03ns        ? ?/sec\ntimestamp/add_time_secs/span                                                                           1.00      3.8±0.06ns        ? ?/sec\ntimestamp/add_time_subsec/duration                              2.10      6.1±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec\ntimestamp/add_time_subsec/span                                                                         1.00      8.1±0.09ns        ? ?/sec\ntimestamp/every_hour_in_week/byhand                             16.15  1679.6±6.13ns        ? ?/sec    1.00    104.0±0.72ns        ? ?/sec\ntimestamp/every_hour_in_week/series                                                                    1.00    105.9±0.66ns        ? ?/sec\ntimestamp/from_seconds/integer                                  14.45     4.7±0.03ns        ? ?/sec    1.00      0.3±0.00ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_conversion                   1.65      7.3±0.02ns        ? ?/sec    1.00      4.4±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_holistic                                                            1.00      4.4±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_static/America-New-York/bundled     1.00     16.0±0.16ns        ? ?/sec\ntimestamp/to_civil_datetime_static/America-New-York/zoneinfo    1.42     18.4±0.11ns        ? ?/sec    1.00     13.0±0.11ns        ? ?/sec\ntimestamp/to_civil_datetime_static/Asia-Shanghai/bundled        1.00     15.2±0.16ns        ? ?/sec\ntimestamp/to_civil_datetime_static/Asia-Shanghai/zoneinfo       3.16     15.7±0.11ns        ? ?/sec    1.00      5.0±0.05ns        ? ?/sec\nzoned/fixed_offset_add_time/duration                            1.00      6.1±0.06ns        ? ?/sec    1.56      9.5±0.05ns        ? ?/sec\nzoned/fixed_offset_add_time/span                                                                       1.00     16.6±0.09ns        ? ?/sec\nzoned/fixed_offset_to_civil_datetime                            1.23      5.6±0.01ns        ? ?/sec    1.00      4.5±0.01ns        ? ?/sec\nzoned/fixed_offset_to_timestamp                                 3.15      1.2±0.01ns        ? ?/sec    1.00      0.4±0.00ns        ? ?/sec\"\u003e\u003cpre lang=\"text\" class=\"notranslate\"\u003e\u003ccode\u003e$ cd bench\n$ cargo bench -- --save-baseline base\n[.. snip ..]\n$ critcmp base -g '(.*)/(?:jiff|chrono)$'\ngroup                                                           baseline//chrono                       baseline//jiff\n-----                                                           ----------------                       --------------\ncivil_datetime/add_days/diffyear/duration                       1.00      8.5±0.08ns        ? ?/sec    1.56     13.3±0.15ns        ? ?/sec\ncivil_datetime/add_days/diffyear/span                                                                  1.00     23.9±0.13ns        ? ?/sec\ncivil_datetime/add_days/sameyear/duration                       1.00      6.8±0.05ns        ? ?/sec    1.96     13.3±0.17ns        ? ?/sec\ncivil_datetime/add_days/sameyear/span                                                                  1.00     23.8±0.13ns        ? ?/sec\ncivil_datetime/to_timestamp_static/bundled                      2.05     22.3±0.24ns        ? ?/sec    1.00     10.9±0.14ns        ? ?/sec\ncivil_datetime/to_timestamp_static/zoneinfo                     1.53     16.2±0.15ns        ? ?/sec    1.00     10.6±0.09ns        ? ?/sec\ncivil_datetime/to_timestamp_tzdb_lookup/bundled                 1.00     32.0±0.15ns        ? ?/sec\ncivil_datetime/to_timestamp_tzdb_lookup/zoneinfo                45.85  1919.7±6.17ns        ? ?/sec    1.00     41.9±0.15ns        ? ?/sec\ndate/add_days/diffyear/duration                                 1.00      5.8±0.05ns        ? ?/sec    1.12      6.5±0.04ns        ? ?/sec\ndate/add_days/diffyear/span                                                                            1.00      6.5±0.04ns        ? ?/sec\ndate/add_days/one/duration                                      1.00      2.1±0.02ns        ? ?/sec    2.55      5.4±0.05ns        ? ?/sec\ndate/add_days/one/span                                                                                 1.00      5.8±0.02ns        ? ?/sec\ndate/add_days/sameyear/duration                                 1.00      2.1±0.01ns        ? ?/sec    3.08      6.5±0.05ns        ? ?/sec\ndate/add_days/sameyear/span                                                                            1.00      6.5±0.05ns        ? ?/sec\ndate/difference_days/duration                                   1.18      3.4±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec\ndate/difference_days/span                                                                              1.00      2.5±0.02ns        ? ?/sec\ndate/tomorrow/diff-month                                        1.00      0.4±0.00ns        ? ?/sec    3.25      1.3±0.01ns        ? ?/sec\ndate/tomorrow/diff-year                                         1.16      1.7±0.01ns        ? ?/sec    1.00      1.4±0.01ns        ? ?/sec\ndate/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec    1.99      0.8±0.00ns        ? ?/sec\ndate/yesterday/diff-month                                       1.00      0.4±0.02ns        ? ?/sec    3.17      1.3±0.01ns        ? ?/sec\ndate/yesterday/diff-year                                        1.85      2.0±0.01ns        ? ?/sec    1.00      1.1±0.01ns        ? ?/sec\ndate/yesterday/same-month                                       1.00      0.4±0.03ns        ? ?/sec    1.72      0.7±0.02ns        ? ?/sec\nparse/civil_datetime                                            2.95     73.6±0.72ns        ? ?/sec    1.00     24.9±0.19ns        ? ?/sec\nparse/rfc2822                                                   3.09     59.9±0.30ns        ? ?/sec    1.00     19.3±0.17ns        ? ?/sec\nparse/strptime/oneshot                                          3.11    197.8±0.80ns        ? ?/sec    1.00     63.6±1.19ns        ? ?/sec\nparse/strptime/prebuilt                                         1.00     77.1±1.44ns        ? ?/sec\nprint/civil_datetime                                            13.10   147.4±0.60ns        ? ?/sec    1.00     11.3±0.04ns        ? ?/sec\nprint/iso8601_duration/long-time/duration/buffer                2.38     46.5±0.34ns        ? ?/sec    1.00     19.5±0.04ns        ? ?/sec\nprint/iso8601_duration/long-time/duration/to_string             3.13     71.7±0.36ns        ? ?/sec    1.00     23.0±0.07ns        ? ?/sec\nprint/iso8601_duration/short/duration/buffer                    2.65     32.3±0.30ns        ? ?/sec    1.00     12.2±0.04ns        ? ?/sec\nprint/iso8601_duration/short/duration/to_string                 2.08     36.8±0.33ns        ? ?/sec    1.00     17.7±0.05ns        ? ?/sec\nprint/iso8601_duration/tiny/duration/buffer                     2.74     31.6±0.32ns        ? ?/sec    1.00     11.6±0.03ns        ? ?/sec\nprint/iso8601_duration/tiny/duration/to_string                  2.28     36.5±0.40ns        ? ?/sec    1.00     16.0±0.08ns        ? ?/sec\nprint/rfc2822/buffer                                            4.91     64.6±0.59ns        ? ?/sec    1.00     13.2±0.03ns        ? ?/sec\nprint/rfc2822/to_string                                         5.75    111.0±0.37ns        ? ?/sec    1.00     19.3±0.05ns        ? ?/sec\nprint/rfc3339/buffer                                            3.79     64.2±0.56ns        ? ?/sec    1.00     17.0±0.14ns        ? ?/sec\nprint/rfc3339/to_string                                         4.75    112.4±0.33ns        ? ?/sec    1.00     23.6±0.11ns        ? ?/sec\nprint/rfc9557/buffer                                                                                   1.00     16.2±0.05ns        ? ?/sec\nprint/rfc9557/to_string                                                                                1.00     22.2±0.07ns        ? ?/sec\nprint/strftime/oneshot/buffer                                   3.90    213.9±1.99ns        ? ?/sec    1.00     54.8±0.32ns        ? ?/sec\nprint/strftime/oneshot/to_string                                3.63    261.3±1.26ns        ? ?/sec    1.00     72.1±0.49ns        ? ?/sec\nprint/strftime/oneshot/zoned                                                                           1.00     65.5±0.64ns        ? ?/sec\nprint/strftime/prebuilt/buffer                                  1.00     85.4±0.52ns        ? ?/sec\nprint/strftime/prebuilt/to_string                               1.00    147.4±0.76ns        ? ?/sec\ntimestamp/add_time_secs/duration                                2.42      6.1±0.08ns        ? ?/sec    1.00      2.5±0.03ns        ? ?/sec\ntimestamp/add_time_secs/span                                                                           1.00      3.8±0.06ns        ? ?/sec\ntimestamp/add_time_subsec/duration                              2.10      6.1±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec\ntimestamp/add_time_subsec/span                                                                         1.00      8.1±0.09ns        ? ?/sec\ntimestamp/every_hour_in_week/byhand                             16.15  1679.6±6.13ns        ? ?/sec    1.00    104.0±0.72ns        ? ?/sec\ntimestamp/every_hour_in_week/series                                                                    1.00    105.9±0.66ns        ? ?/sec\ntimestamp/from_seconds/integer                                  14.45     4.7±0.03ns        ? ?/sec    1.00      0.3±0.00ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_conversion                   1.65      7.3±0.02ns        ? ?/sec    1.00      4.4±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_holistic                                                            1.00      4.4±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_static/America-New-York/bundled     1.00     16.0±0.16ns        ? ?/sec\ntimestamp/to_civil_datetime_static/America-New-York/zoneinfo    1.42     18.4±0.11ns        ? ?/sec    1.00     13.0±0.11ns        ? ?/sec\ntimestamp/to_civil_datetime_static/Asia-Shanghai/bundled        1.00     15.2±0.16ns        ? ?/sec\ntimestamp/to_civil_datetime_static/Asia-Shanghai/zoneinfo       3.16     15.7±0.11ns        ? ?/sec    1.00      5.0±0.05ns        ? ?/sec\nzoned/fixed_offset_add_time/duration                            1.00      6.1±0.06ns        ? ?/sec    1.56      9.5±0.05ns        ? ?/sec\nzoned/fixed_offset_add_time/span                                                                       1.00     16.6±0.09ns        ? ?/sec\nzoned/fixed_offset_to_civil_datetime                            1.23      5.6±0.01ns        ? ?/sec    1.00      4.5±0.01ns        ? ?/sec\nzoned/fixed_offset_to_timestamp                                 3.15      1.2±0.01ns        ? ?/sec    1.00      0.4±0.00ns        ? ?/sec\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eQuestions about benchmarks are welcome in\n\u003ca href=\"https://github.com/BurntSushi/jiff/discussions\"\u003eDiscussions on GitHub\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ca href=\"https://docs.rs/time\" rel=\"nofollow\"\u003e\u003ccode\u003etime\u003c/code\u003e\u003c/a\u003e (v0.3.36)\u003c/h2\u003e\u003ca id=\"user-content-time-v0336\" class=\"anchor\" aria-label=\"Permalink: time (v0.3.36)\" href=\"#time-v0336\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003etime\u003c/code\u003e is a Rust datetime library that provides a time zone offset aware\ndatetime type.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor the following comparisons, a \u003ccode\u003eCargo.toml\u003c/code\u003e with the following dependencies\nshould be able to run any of the programs in this section:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"anyhow = \u0026quot;1.0.81\u0026quot;\njiff = { version = \u0026quot;0.2.0\u0026quot;, features = [\u0026quot;serde\u0026quot;] }\ntime = { version = \u0026quot;0.3.36\u0026quot;, features = [\u0026quot;local-offset\u0026quot;, \u0026quot;macros\u0026quot;, \u0026quot;parsing\u0026quot;] }\ntime-tz = \u0026quot;2.0.0\u0026quot;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eanyhow\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.81\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003ejiff\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.2.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eserde\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003etime\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.3.36\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003elocal-offset\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emacros\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eparsing\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003etime-tz\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e2.0.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTime zone database integration\u003c/h3\u003e\u003ca id=\"user-content-time-zone-database-integration-1\" class=\"anchor\" aria-label=\"Permalink: Time zone database integration\" href=\"#time-zone-database-integration-1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLike \u003ccode\u003echrono\u003c/code\u003e, the \u003ccode\u003etime\u003c/code\u003e crate does not come with any out of the box\nfunctionality for reading your system's copy of the Time Zone Database.\nHowever, there is a third party crate, \u003ca href=\"https://docs.rs/time-tz\" rel=\"nofollow\"\u003e\u003ccode\u003etime-tz\u003c/code\u003e\u003c/a\u003e\nthat provides some time zone support in a fashion similar to \u003ccode\u003echrono-tz\u003c/code\u003e. That\nis, it requires bundling the time zone data into your binary and does not\nsupport reading the system copy of the Time Zone Database when available.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eNote also that \u003ccode\u003etime\u003c/code\u003e does not provide the extension points necessary in its API\nto make handling time zone aware datetimes ergonomic. Indeed, many operations\nare not expressible at all.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe main thing \u003ccode\u003etime\u003c/code\u003e supports is a concept of \"local\" time. In particular, it\nis limited to determining your system's default time zone offset, but nothing\nmore. That is, it doesn't support DST safe arithmetic:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse time::{ext::NumericalDuration, macros::datetime, Duration};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // We create a fixed datetime for testing purposes,\n    // but it's the same sort of value we would get back\n    // from `OffsetDateTime::now_local()`.\n    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);\n    let dt2 = dt1.checked_add(1.hours())\n      .context(\u0026quot;datetime arithmetic failed\u0026quot;)?;\n    // The 2 o'clock hour didn't exist on 2024-03-10\n    // in New York.\n    assert_eq!(dt2.to_string(), \u0026quot;2024-03-10 2:30:00.0 -05:00:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003eext\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNumericalDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e macros\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edatetime\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// We create a fixed datetime for testing purposes,\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// but it's the same sort of value we would get back\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// from `OffsetDateTime::now_local()`.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e dt1 = \u003cspan class=\"pl-en\"\u003edatetime\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e03\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e01\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e -\u003cspan class=\"pl-c1\"\u003e05\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e dt2 = dt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n      \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"datetime arithmetic failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// The 2 o'clock hour didn't exist on 2024-03-10\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// in New York.\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003edt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 2:30:00.0 -05:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003etime\u003c/code\u003e, in its present design, is fundamentally incapable of doing daylight\nsaving time safe arithmetic because its \u003ccode\u003eOffsetDateTime\u003c/code\u003e type doesn't know\nanything about the time zone rules. Compare this with Jiff, which lets you not\nonly create a datetime with an offset, but with a \u003cem\u003etime zone\u003c/em\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2024, 3, 10).at(1, 30, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = zdt1.checked_add(1.hour())?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-03-10T03:30:00-04:00[America/New_York]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10T03:30:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you use \u003ccode\u003etime-tz\u003c/code\u003e, then you can make the above example with \u003ccode\u003etime\u003c/code\u003e work:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use anyhow::Context;\nuse time::{ext::NumericalDuration, macros::datetime, Duration};\nuse time_tz::{OffsetDateTimeExt, Tz};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let tz = time_tz::timezones::db::america::NEW_YORK;\n\n    // We create a fixed datetime for testing purposes,\n    // but it's the same sort of value we would get back\n    // from `OffsetDateTime::now_local()`.\n    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);\n    let dt2 = dt1.checked_add(1.hours())\n      .context(\u0026quot;datetime arithmetic failed\u0026quot;)?\n      .to_timezone(tz);\n    assert_eq!(dt2.to_string(), \u0026quot;2024-03-10 3:30:00.0 -04:00:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eContext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003eext\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNumericalDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e macros\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edatetime\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eOffsetDateTimeExt\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e tz = time_tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003etimezones\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edb\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eamerica\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNEW_YORK\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// We create a fixed datetime for testing purposes,\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// but it's the same sort of value we would get back\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// from `OffsetDateTime::now_local()`.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e dt1 = \u003cspan class=\"pl-en\"\u003edatetime\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e03\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e10\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e01\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e -\u003cspan class=\"pl-c1\"\u003e05\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e dt2 = dt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n      \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003econtext\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"datetime arithmetic failed\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\n      \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_timezone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003etz\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003edt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-03-10 3:30:00.0 -04:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBut note that you have to be careful to call \u003ccode\u003e.to_timezone()\u003c/code\u003e before printing\nthe datetime. In particular, there is no time zone aware datetime type.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn my comparison with Chrono I went through a lot of examples involving\ntime zones. I did this because Chrono supports DST safe arithmetic generally,\nbut with a lot of nuanced differences from what Jiff supports. Conversely,\n\u003ccode\u003etime\u003c/code\u003e doesn't have a time zone aware datetime type. And the time zone support\nprovided by \u003ccode\u003etime-tz\u003c/code\u003e is extremely limited. So at this time, in this document,\nwe won't belabor the point.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003etime\u003c/code\u003e supports its own custom format description\u003c/h3\u003e\u003ca id=\"user-content-time-supports-its-own-custom-format-description\" class=\"anchor\" aria-label=\"Permalink: time supports its own custom format description\" href=\"#time-supports-its-own-custom-format-description\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSome users may find this easier to use:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use time::{macros::format_description, OffsetDateTime};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let format = format_description!(\n        \u0026quot;[year]-[month]-[day] [hour]:[minute]:[second] \\\n         [offset_hour sign:mandatory]:[offset_minute]:[offset_second]\u0026quot;\n    );\n    let odt = OffsetDateTime::parse(\u0026quot;2024-07-11 22:49:00 -04:00:00\u0026quot;, \u0026amp;format)?;\n    assert_eq!(odt.to_string(), \u0026quot;2024-07-11 22:49:00.0 -04:00:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003emacros\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eformat_description\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eOffsetDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e format = \u003cspan class=\"pl-en\"\u003eformat_description\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-s\"\u003e\"[year]-[month]-[day] [hour]:[minute]:[second] \u003cspan class=\"pl-cce\"\u003e\\\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-cce\"\u003e\u003c/span\u003e         [offset_hour sign:mandatory]:[offset_minute]:[offset_second]\"\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e odt = \u003cspan class=\"pl-smi\"\u003eOffsetDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"2024-07-11 22:49:00 -04:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003eformat\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eodt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-07-11 22:49:00.0 -04:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff does support a \u003ccode\u003estrptime\u003c/code\u003e/\u003ccode\u003estrftime\u003c/code\u003e style API via the\n\u003ccode\u003ejiff::fmt::strtime\u003c/code\u003e module:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::Zoned;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt = Zoned::strptime(\n      \u0026quot;%Y-%m-%d %H:%M:%S %:z\u0026quot;,\n      \u0026quot;2024-07-11 22:49:00 -04:00:00\u0026quot;,\n    )?;\n    assert_eq!(zdt.to_string(), \u0026quot;2024-07-11T22:49:00-04:00[-04:00]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eZoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt = \u003cspan class=\"pl-smi\"\u003eZoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003estrptime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n      \u003cspan class=\"pl-s\"\u003e\"%Y-%m-%d %H:%M:%S %:z\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"pl-s\"\u003e\"2024-07-11 22:49:00 -04:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-07-11T22:49:00-04:00[-04:00]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003etime\u003c/code\u003e also supports \u003ccode\u003estrptime\u003c/code\u003e/\u003ccode\u003estrftime\u003c/code\u003e style APIs:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use time::OffsetDateTime;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // I don't believe `time` supports `%:z`, so we just drop the colons here.\n    let format = time::format_description::parse_strftime_borrowed(\n        \u0026quot;%Y-%m-%d %H:%M:%S %z\u0026quot;\n    )?;\n    let odt = OffsetDateTime::parse(\u0026quot;2024-07-11 22:49:00 -0400\u0026quot;, \u0026amp;format)?;\n    assert_eq!(odt.to_string(), \u0026quot;2024-07-11 22:49:00.0 -04:00:00\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eOffsetDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// I don't believe `time` supports `%:z`, so we just drop the colons here.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e format = time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eformat_description\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse_strftime_borrowed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\n        \u003cspan class=\"pl-s\"\u003e\"%Y-%m-%d %H:%M:%S %z\"\u003c/span\u003e\n    \u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e odt = \u003cspan class=\"pl-smi\"\u003eOffsetDateTime\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"2024-07-11 22:49:00 -0400\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003eformat\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eodt\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-07-11 22:49:00.0 -04:00:00\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports rounding datetimes\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-rounding-datetimes\" class=\"anchor\" aria-label=\"Permalink: Jiff supports rounding datetimes\" href=\"#jiff-supports-rounding-datetimes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe use a \u003ccode\u003eZoned\u003c/code\u003e with a \u003ccode\u003eTimeZone\u003c/code\u003e that has a fixed offset. This is same as\n\u003ccode\u003etime\u003c/code\u003e's \u003ccode\u003eOffsetDateTime\u003c/code\u003e type:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, tz::{self, TimeZone}, Unit, Zoned};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let tz = TimeZone::fixed(tz::offset(-4));\n    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).to_zoned(tz)?;\n    let zdt2 = zdt1.round(Unit::Hour)?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-07-11T17:00:00-04:00[-04:00]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e tz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eself\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eZoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e tz = \u003cspan class=\"pl-smi\"\u003eTimeZone\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efixed\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003etz\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eoffset\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e16\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e46\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_zoned\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003etz\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-07-11T17:00:00-04:00[-04:00]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNote though that because Jiff has support for time zones, you generally\nshouldn't need to (and shouldn't \u003cem\u003ewant\u003c/em\u003e to) use fixed offset datetimes. It's\nbecause they don't take time zone rules into account and thus do not provide\nDST safe arithmetic. Instead, the code above should be written like this\n(unless you have a very specific reason to do otherwise):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // Can also use `.to_zoned(TimeZone::system())` to use your system's\n    // default time zone.\n    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = zdt1.round(Unit::Hour)?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2024-07-11T17:00:00-04:00[America/New_York]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Can also use `.to_zoned(TimeZone::system())` to use your system's\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// default time zone.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e16\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e46\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2024-07-11T17:00:00-04:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFrom here on, we won't use fixed offset datetimes in order to avoid encouraging\ntheir use.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003etime\u003c/code\u003e crate has no rounding APIs.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports rounding durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-rounding-durations-1\" class=\"anchor\" aria-label=\"Permalink: Jiff supports rounding durations\" href=\"#jiff-supports-rounding-durations-1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn Jiff, one can round the duration computed between two datetimes\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n\n    let round_options = ZonedDifference::new(\u0026amp;zdt2)\n        .largest(Unit::Year)\n        .smallest(Unit::Day)\n        .mode(RoundMode::HalfExpand);\n    let span = zdt1.until(round_options)?;\n    assert_eq!(span, 22.years().months(7).days(24).fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2001\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e8\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e38\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e round_options = \u003cspan class=\"pl-smi\"\u003eZonedDifference\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e\u0026amp;\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eYear\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003esmallest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDay\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n        \u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eRoundMode\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHalfExpand\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003euntil\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eround_options\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e22\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eyears\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003emonths\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003edays\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003etime\u003c/code\u003e crate has no rounding APIs.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff provides support for calendar arithmetic\u003c/h3\u003e\u003ca id=\"user-content-jiff-provides-support-for-calendar-arithmetic\" class=\"anchor\" aria-label=\"Permalink: Jiff provides support for calendar arithmetic\" href=\"#jiff-provides-support-for-calendar-arithmetic\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWith Jiff, you can add durations with calendar units:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{civil::date, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let zdt1 = date(2024, 7, 11).at(21, 0, 0, 0).in_tz(\u0026quot;America/New_York\u0026quot;)?;\n    let zdt2 = zdt1.checked_add(2.years().months(6).days(1))?;\n    assert_eq!(zdt2.to_string(), \u0026quot;2027-01-12T21:00:00-05:00[America/New_York]\u0026quot;);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003ecivil\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003edate\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt1 = \u003cspan class=\"pl-en\"\u003edate\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2024\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eat\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ein_tz\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\"America/New_York\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e zdt2 = zdt1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003echecked_add\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eyears\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003emonths\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e6\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003edays\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ezdt2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eto_string\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\"2027-01-12T21:00:00-05:00[America/New_York]\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003etime\u003c/code\u003e crate does provide a way to construct a \u003ccode\u003eDuration\u003c/code\u003e from units of\ndays via \u003ccode\u003eDuration::days\u003c/code\u003e, but this of course requires assuming that all days\nare 24 hours long. And \u003ccode\u003etime\u003c/code\u003e does not support adding years or months.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff supports conveniently re-balancing durations\u003c/h3\u003e\u003ca id=\"user-content-jiff-supports-conveniently-re-balancing-durations\" class=\"anchor\" aria-label=\"Permalink: Jiff supports conveniently re-balancing durations\" href=\"#jiff-supports-conveniently-re-balancing-durations\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAside from calendar arithmetic, Jiff also supports re-balancing durations\nbased on what you want the largest unit to be:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{SpanRound, ToSpan, Unit};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    // Balance down to seconds.\n    let span1 = 4.hours().minutes(36).seconds(59);\n    let span2 = span1.round(SpanRound::new().largest(Unit::Second))?;\n    assert_eq!(span2, 16_619.seconds().fieldwise());\n\n    // Now go back by balancing up to hours.\n    let span1 = 16_619.seconds();\n    let span2 = span1.round(SpanRound::new().largest(Unit::Hour))?;\n    assert_eq!(span2, 4.hours().minutes(36).seconds(59).fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-c\"\u003e// Balance down to seconds.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e36\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eseconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eSecond\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eseconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-c\"\u003e// Now go back by balancing up to hours.\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span1 = \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eseconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span2 = span1\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eround\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eSpanRound\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003enew\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003elargest\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eUnit\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan2\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eminutes\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e36\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eseconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003etime\u003c/code\u003e crate's \u003ccode\u003eDuration\u003c/code\u003e type can go from bigger units down to smaller\nunits easily enough:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use time::{ext::NumericalDuration, Duration};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let span = 4.hours() + 36.minutes() + 59.seconds();\n    assert_eq!(span.whole_seconds(), 16_619);\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003eext\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNumericalDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003ehours\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e + \u003cspan class=\"pl-c1\"\u003e36\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eminutes\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e + \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eseconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_seconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBut going from smaller units back up to larger units is difficult:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use time::{ext::NumericalDuration, Duration};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let span = 16_619.seconds();\n    assert_eq!(span.whole_hours(), 4);\n    assert_eq!(span.whole_minutes(), 276);\n    assert_eq!(span.whole_seconds(), 16_619);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003eext\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNumericalDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eseconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_hours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_minutes\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e276\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_seconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNotice that the accessors just report how many whole units the span is. You\ncan't get the span broken down into smaller units. To achieve that, you need to\ndo the arithmetic yourself:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use time::{convert::{Hour, Minute, Second}, ext::NumericalDuration, Duration};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let mut span = 16_619.seconds();\n    assert_eq!(span.whole_hours(), 4);\n    assert_eq!(span.whole_minutes() % Minute::per(Hour) as i64, 36);\n    assert_eq!(span.whole_seconds() % Second::per(Minute) as i64, 59);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e time\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003econvert\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eMinute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eSecond\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e ext\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eNumericalDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e \u003cspan class=\"pl-k\"\u003emut\u003c/span\u003e span = \u003cspan class=\"pl-c1\"\u003e16_619\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eseconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_hours\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_minutes\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e % \u003cspan class=\"pl-v\"\u003eMinute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eper\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eHour\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eas\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ei64\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e36\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ewhole_seconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e % \u003cspan class=\"pl-v\"\u003eSecond\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003eper\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eMinute\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eas\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ei64\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e59\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff is generally faster than \u003ccode\u003etime\u003c/code\u003e\u003c/h3\u003e\u003ca id=\"user-content-jiff-is-generally-faster-than-time\" class=\"anchor\" aria-label=\"Permalink: Jiff is generally faster than time\" href=\"#jiff-is-generally-faster-than-time\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen it comes to parsing and printing, Jiff is generally faster than \u003ccode\u003etime\u003c/code\u003e\nalthough not always. \u003ccode\u003etime\u003c/code\u003e is sometimes faster than Jiff on date arithmetic,\nbut not by much. (Some of these may be due to faster equality comparisons on\ndate values, on which \u003ccode\u003etime\u003c/code\u003e is legitimately faster at than Jiff at present.)\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe following results were collected with \u003ccode\u003etime 0.3.47\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"$ cd bench\n$ cargo bench -- --save-baseline baseline\n[.. snip ..]\n$ critcmp base -g '(.*)/(?:jiff|time)$'\ngroup                                                           baseline//time                       baseline//jiff\n-----                                                           --------------                       --------------\ncivil_datetime/add_days/diffyear/duration                       1.00      7.8±0.08ns        ? ?/sec  1.67     12.9±0.19ns        ? ?/sec\ncivil_datetime/add_days/diffyear/span                                                                1.00     18.0±0.28ns        ? ?/sec\ncivil_datetime/add_days/sameyear/duration                       1.00      7.8±0.11ns        ? ?/sec  1.66     12.9±0.16ns        ? ?/sec\ncivil_datetime/add_days/sameyear/span                                                                1.00     18.0±0.25ns        ? ?/sec\ndate/add_days/diffyear/duration                                 1.00      3.8±0.02ns        ? ?/sec  1.67      6.3±0.04ns        ? ?/sec\ndate/add_days/diffyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec\ndate/add_days/one/duration                                      1.00      3.8±0.03ns        ? ?/sec  1.38      5.2±0.03ns        ? ?/sec\ndate/add_days/one/span                                                                               1.00      5.8±0.06ns        ? ?/sec\ndate/add_days/sameyear/duration                                 1.00      3.8±0.04ns        ? ?/sec  1.68      6.4±0.07ns        ? ?/sec\ndate/add_days/sameyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec\ndate/days_in_month/leap/feb                                     1.90      1.1±0.01ns        ? ?/sec  1.00      0.6±0.03ns        ? ?/sec\ndate/days_in_month/leap/nofeb                                   2.70      1.0±0.01ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec\ndate/days_in_month/noleap/feb                                   2.78      1.1±0.02ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec\ndate/days_in_month/noleap/nofeb                                 2.70      1.0±0.02ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec\ndate/difference_days/duration                                   1.00      2.1±0.02ns        ? ?/sec  1.41      2.9±0.04ns        ? ?/sec\ndate/difference_days/span                                                                            1.00      2.4±0.03ns        ? ?/sec\ndate/tomorrow/diff-month                                        1.00      0.4±0.02ns        ? ?/sec  3.42      1.4±0.01ns        ? ?/sec\ndate/tomorrow/diff-year                                         1.00      1.0±0.01ns        ? ?/sec  1.59      1.5±0.01ns        ? ?/sec\ndate/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec  2.25      0.9±0.01ns        ? ?/sec\ndate/yesterday/diff-month                                       1.00      0.4±0.01ns        ? ?/sec  3.65      1.4±0.02ns        ? ?/sec\ndate/yesterday/diff-year                                        1.00      0.9±0.01ns        ? ?/sec  1.35      1.2±0.02ns        ? ?/sec\ndate/yesterday/same-month                                       1.00      0.4±0.02ns        ? ?/sec  2.06      0.8±0.01ns        ? ?/sec\ndatetime/add_years_months_days                                                                       1.00     29.1±0.18ns        ? ?/sec\nparse/civil_datetime                                            1.00     12.9±0.19ns        ? ?/sec  1.63     21.1±0.19ns        ? ?/sec\nparse/rfc2822                                                   2.24     43.4±1.90ns        ? ?/sec  1.00     19.4±0.15ns        ? ?/sec\nparse/strptime/oneshot                                                                               1.00     62.2±0.39ns        ? ?/sec\nparse/strptime/prebuilt                                         1.00     73.7±0.91ns        ? ?/sec\nprint/civil_datetime                                            3.27     37.4±0.32ns        ? ?/sec  1.00     11.4±0.04ns        ? ?/sec\nprint/rfc2822/buffer                                            1.55     20.4±0.08ns        ? ?/sec  1.00     13.2±0.05ns        ? ?/sec\nprint/rfc2822/to_string                                         3.61     72.0±1.25ns        ? ?/sec  1.00     19.9±0.06ns        ? ?/sec\nprint/rfc3339/buffer                                            1.33     22.1±0.29ns        ? ?/sec  1.00     16.7±0.11ns        ? ?/sec\nprint/rfc3339/to_string                                         2.91     68.1±1.30ns        ? ?/sec  1.00     23.4±0.12ns        ? ?/sec\nprint/rfc9557/buffer                                                                                 1.00     16.2±0.07ns        ? ?/sec\nprint/rfc9557/to_string                                                                              1.00     22.6±0.20ns        ? ?/sec\nprint/strftime/oneshot/buffer                                   6.88    421.5±1.39ns        ? ?/sec  1.00     61.3±0.82ns        ? ?/sec\nprint/strftime/oneshot/to_string                                5.59    434.0±1.44ns        ? ?/sec  1.00     77.7±0.96ns        ? ?/sec\nprint/strftime/oneshot/zoned                                                                         1.00     74.6±1.07ns        ? ?/sec\nprint/strftime/prebuilt/buffer                                  1.00     97.7±0.99ns        ? ?/sec\nprint/strftime/prebuilt/buffer/bespoke                          1.00    105.8±1.45ns        ? ?/sec\nprint/strftime/prebuilt/to_string                               1.00    165.3±1.19ns        ? ?/sec\nprint/strftime/prebuilt/to_string/bespoke                       1.00    175.0±1.79ns        ? ?/sec\ntimestamp/add_time_secs/duration                                3.82      9.6±0.04ns        ? ?/sec  1.00      2.5±0.03ns        ? ?/sec\ntimestamp/add_time_secs/span                                                                         1.00      3.7±0.05ns        ? ?/sec\ntimestamp/add_time_subsec/duration                              3.33      9.7±0.09ns        ? ?/sec  1.00      2.9±0.03ns        ? ?/sec\ntimestamp/add_time_subsec/span                                                                       1.00      7.8±0.08ns        ? ?/sec\ntimestamp/every_hour_in_week/byhand                             14.30 1530.8±16.96ns        ? ?/sec  1.00    107.1±0.74ns        ? ?/sec\ntimestamp/every_hour_in_week/series                                                                  1.00    105.8±1.01ns        ? ?/sec\ntimestamp/from_seconds/integer                                  11.69     4.4±0.03ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_conversion                   1.00      3.9±0.03ns        ? ?/sec  1.49      5.8±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_holistic                     1.00      4.6±0.03ns        ? ?/sec  1.04      4.8±0.04ns        ? ?/sec\nzoned/fixed_offset_add_time/duration                            1.00      9.6±0.09ns        ? ?/sec  1.06     10.3±0.08ns        ? ?/sec\nzoned/fixed_offset_add_time/span                                                                     1.00     16.9±0.12ns        ? ?/sec\nzoned/fixed_offset_to_civil_datetime                            1.00      0.6±0.00ns        ? ?/sec  7.32      4.2±0.01ns        ? ?/sec\nzoned/fixed_offset_to_timestamp                                 6.08      1.8±0.02ns        ? ?/sec  1.00      0.3±0.01ns        ? ?/sec\"\u003e\u003cpre lang=\"text\" class=\"notranslate\"\u003e\u003ccode\u003e$ cd bench\n$ cargo bench -- --save-baseline baseline\n[.. snip ..]\n$ critcmp base -g '(.*)/(?:jiff|time)$'\ngroup                                                           baseline//time                       baseline//jiff\n-----                                                           --------------                       --------------\ncivil_datetime/add_days/diffyear/duration                       1.00      7.8±0.08ns        ? ?/sec  1.67     12.9±0.19ns        ? ?/sec\ncivil_datetime/add_days/diffyear/span                                                                1.00     18.0±0.28ns        ? ?/sec\ncivil_datetime/add_days/sameyear/duration                       1.00      7.8±0.11ns        ? ?/sec  1.66     12.9±0.16ns        ? ?/sec\ncivil_datetime/add_days/sameyear/span                                                                1.00     18.0±0.25ns        ? ?/sec\ndate/add_days/diffyear/duration                                 1.00      3.8±0.02ns        ? ?/sec  1.67      6.3±0.04ns        ? ?/sec\ndate/add_days/diffyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec\ndate/add_days/one/duration                                      1.00      3.8±0.03ns        ? ?/sec  1.38      5.2±0.03ns        ? ?/sec\ndate/add_days/one/span                                                                               1.00      5.8±0.06ns        ? ?/sec\ndate/add_days/sameyear/duration                                 1.00      3.8±0.04ns        ? ?/sec  1.68      6.4±0.07ns        ? ?/sec\ndate/add_days/sameyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec\ndate/days_in_month/leap/feb                                     1.90      1.1±0.01ns        ? ?/sec  1.00      0.6±0.03ns        ? ?/sec\ndate/days_in_month/leap/nofeb                                   2.70      1.0±0.01ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec\ndate/days_in_month/noleap/feb                                   2.78      1.1±0.02ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec\ndate/days_in_month/noleap/nofeb                                 2.70      1.0±0.02ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec\ndate/difference_days/duration                                   1.00      2.1±0.02ns        ? ?/sec  1.41      2.9±0.04ns        ? ?/sec\ndate/difference_days/span                                                                            1.00      2.4±0.03ns        ? ?/sec\ndate/tomorrow/diff-month                                        1.00      0.4±0.02ns        ? ?/sec  3.42      1.4±0.01ns        ? ?/sec\ndate/tomorrow/diff-year                                         1.00      1.0±0.01ns        ? ?/sec  1.59      1.5±0.01ns        ? ?/sec\ndate/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec  2.25      0.9±0.01ns        ? ?/sec\ndate/yesterday/diff-month                                       1.00      0.4±0.01ns        ? ?/sec  3.65      1.4±0.02ns        ? ?/sec\ndate/yesterday/diff-year                                        1.00      0.9±0.01ns        ? ?/sec  1.35      1.2±0.02ns        ? ?/sec\ndate/yesterday/same-month                                       1.00      0.4±0.02ns        ? ?/sec  2.06      0.8±0.01ns        ? ?/sec\ndatetime/add_years_months_days                                                                       1.00     29.1±0.18ns        ? ?/sec\nparse/civil_datetime                                            1.00     12.9±0.19ns        ? ?/sec  1.63     21.1±0.19ns        ? ?/sec\nparse/rfc2822                                                   2.24     43.4±1.90ns        ? ?/sec  1.00     19.4±0.15ns        ? ?/sec\nparse/strptime/oneshot                                                                               1.00     62.2±0.39ns        ? ?/sec\nparse/strptime/prebuilt                                         1.00     73.7±0.91ns        ? ?/sec\nprint/civil_datetime                                            3.27     37.4±0.32ns        ? ?/sec  1.00     11.4±0.04ns        ? ?/sec\nprint/rfc2822/buffer                                            1.55     20.4±0.08ns        ? ?/sec  1.00     13.2±0.05ns        ? ?/sec\nprint/rfc2822/to_string                                         3.61     72.0±1.25ns        ? ?/sec  1.00     19.9±0.06ns        ? ?/sec\nprint/rfc3339/buffer                                            1.33     22.1±0.29ns        ? ?/sec  1.00     16.7±0.11ns        ? ?/sec\nprint/rfc3339/to_string                                         2.91     68.1±1.30ns        ? ?/sec  1.00     23.4±0.12ns        ? ?/sec\nprint/rfc9557/buffer                                                                                 1.00     16.2±0.07ns        ? ?/sec\nprint/rfc9557/to_string                                                                              1.00     22.6±0.20ns        ? ?/sec\nprint/strftime/oneshot/buffer                                   6.88    421.5±1.39ns        ? ?/sec  1.00     61.3±0.82ns        ? ?/sec\nprint/strftime/oneshot/to_string                                5.59    434.0±1.44ns        ? ?/sec  1.00     77.7±0.96ns        ? ?/sec\nprint/strftime/oneshot/zoned                                                                         1.00     74.6±1.07ns        ? ?/sec\nprint/strftime/prebuilt/buffer                                  1.00     97.7±0.99ns        ? ?/sec\nprint/strftime/prebuilt/buffer/bespoke                          1.00    105.8±1.45ns        ? ?/sec\nprint/strftime/prebuilt/to_string                               1.00    165.3±1.19ns        ? ?/sec\nprint/strftime/prebuilt/to_string/bespoke                       1.00    175.0±1.79ns        ? ?/sec\ntimestamp/add_time_secs/duration                                3.82      9.6±0.04ns        ? ?/sec  1.00      2.5±0.03ns        ? ?/sec\ntimestamp/add_time_secs/span                                                                         1.00      3.7±0.05ns        ? ?/sec\ntimestamp/add_time_subsec/duration                              3.33      9.7±0.09ns        ? ?/sec  1.00      2.9±0.03ns        ? ?/sec\ntimestamp/add_time_subsec/span                                                                       1.00      7.8±0.08ns        ? ?/sec\ntimestamp/every_hour_in_week/byhand                             14.30 1530.8±16.96ns        ? ?/sec  1.00    107.1±0.74ns        ? ?/sec\ntimestamp/every_hour_in_week/series                                                                  1.00    105.8±1.01ns        ? ?/sec\ntimestamp/from_seconds/integer                                  11.69     4.4±0.03ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_conversion                   1.00      3.9±0.03ns        ? ?/sec  1.49      5.8±0.04ns        ? ?/sec\ntimestamp/to_civil_datetime_offset_holistic                     1.00      4.6±0.03ns        ? ?/sec  1.04      4.8±0.04ns        ? ?/sec\nzoned/fixed_offset_add_time/duration                            1.00      9.6±0.09ns        ? ?/sec  1.06     10.3±0.08ns        ? ?/sec\nzoned/fixed_offset_add_time/span                                                                     1.00     16.9±0.12ns        ? ?/sec\nzoned/fixed_offset_to_civil_datetime                            1.00      0.6±0.00ns        ? ?/sec  7.32      4.2±0.01ns        ? ?/sec\nzoned/fixed_offset_to_timestamp                                 6.08      1.8±0.02ns        ? ?/sec  1.00      0.3±0.01ns        ? ?/sec\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eQuestions about benchmarks are welcome in\n\u003ca href=\"https://github.com/BurntSushi/jiff/discussions\"\u003eDiscussions on GitHub\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ca href=\"https://docs.rs/hifitime\" rel=\"nofollow\"\u003e\u003ccode\u003ehifitime\u003c/code\u003e\u003c/a\u003e (v3.9.0)\u003c/h2\u003e\u003ca id=\"user-content-hifitime-v390\" class=\"anchor\" aria-label=\"Permalink: hifitime (v3.9.0)\" href=\"#hifitime-v390\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ehifitime\u003c/code\u003e is a datetime library with a focus on engineering and scientific\ncalculations where general relativity and time dilation matter. It supports\nconversion between many different time scales: TAI, Terrestrial Time, UTC, GPST\nand more. It also supports leap seconds.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor the following comparisons, a \u003ccode\u003eCargo.toml\u003c/code\u003e with the following dependencies\nshould be able to run any of the programs in this section:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"anyhow = \u0026quot;1.0.81\u0026quot;\nhifitime = \u0026quot;3.9.0\u0026quot;\njiff = { version = \u0026quot;0.2.0\u0026quot;, features = [\u0026quot;serde\u0026quot;] }\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eanyhow\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.81\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003ehifitime\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e3.9.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003ejiff\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.2.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eserde\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTime zone database integration\u003c/h3\u003e\u003ca id=\"user-content-time-zone-database-integration-2\" class=\"anchor\" aria-label=\"Permalink: Time zone database integration\" href=\"#time-zone-database-integration-2\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLike the \u003ccode\u003etime\u003c/code\u003e crate, \u003ccode\u003ehifitime\u003c/code\u003e does not support time zones and does not have\nany integration with the Time Zone Database. \u003ccode\u003ehifitime\u003c/code\u003e doesn't have any\nequivalent to \u003ccode\u003eOffsetDateTime\u003c/code\u003e like in \u003ccode\u003etime\u003c/code\u003e either. The only datetime type\nthat \u003ccode\u003ehifitime\u003c/code\u003e has is \u003ccode\u003eEpoch\u003c/code\u003e, and it is an absolute time. While you can\nconvert between it and civil time (assuming civil time is in UTC), there is no\ndata type in \u003ccode\u003ehifitime\u003c/code\u003e for representing civil time.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ccode\u003ehifitime\u003c/code\u003e supports leap seconds\u003c/h3\u003e\u003ca id=\"user-content-hifitime-supports-leap-seconds\" class=\"anchor\" aria-label=\"Permalink: hifitime supports leap seconds\" href=\"#hifitime-supports-leap-seconds\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn particular, when computing a duration from two \u003ccode\u003eEpoch\u003c/code\u003e values that spans\na positive leap second (a second gets repeated), \u003ccode\u003ehifitime\u003c/code\u003e will correctly\nreport the accurate duration. With that said, to get an accurate duration, one\nof the two time scales has to be converted to to TAI (or another time scale\nwhich does not have leap seconds):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use hifitime::{Duration, Epoch, TimeScale};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let e1: Epoch = \u0026quot;2015-06-30T23:00:00 UTC\u0026quot;.parse()?;\n    let e2: Epoch = \u0026quot;2015-07-01T00:00:00 UTC\u0026quot;.parse()?;\n    let e2 = e2.to_time_scale(TimeScale::TAI);\n\n    let duration = e2 - e1;\n    assert_eq!(duration, Duration::from_seconds(3_601.0));\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e hifitime\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eEpoch\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eTimeScale\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e e1\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEpoch\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2015-06-30T23:00:00 UTC\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e e2\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEpoch\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2015-07-01T00:00:00 UTC\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e e2 = e2\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eto_time_scale\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eTimeScale\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTAI\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e duration = e2 - e1\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003eduration\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003efrom_seconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e3_601.0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eJiff, however, \u003ca href=\"https://github.com/BurntSushi/jiff/issues/7\" data-hovercard-type=\"issue\" data-hovercard-url=\"/BurntSushi/jiff/issues/7/hovercard\"\u003edoes not support leap seconds\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{Timestamp, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let ts1: Timestamp = \u0026quot;2015-06-30T23:00:00Z\u0026quot;.parse()?;\n    let ts2: Timestamp = \u0026quot;2015-07-01T00:00:00Z\u0026quot;.parse()?;\n    let span = ts2 - ts1;\n    assert_eq!(span, 3_600.seconds().fieldwise());\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTimestamp\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e ts1\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eTimestamp\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2015-06-30T23:00:00Z\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e ts2\u003cspan class=\"pl-kos\"\u003e:\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eTimestamp\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"2015-07-01T00:00:00Z\"\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003e\u003cspan class=\"pl-en\"\u003eparse\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e span = ts2 - ts1\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003espan\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e3_600\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eseconds\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003efieldwise\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSo in this case, Jiff reports \u003ccode\u003e3,600\u003c/code\u003e seconds as the duration, but the \u003cem\u003eactual\u003c/em\u003e\nduration was \u003ccode\u003e3,601\u003c/code\u003e seconds, as reported by \u003ccode\u003ehifitime\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eJiff makes checked or saturating arithmetic explicit\u003c/h3\u003e\u003ca id=\"user-content-jiff-makes-checked-or-saturating-arithmetic-explicit\" class=\"anchor\" aria-label=\"Permalink: Jiff makes checked or saturating arithmetic explicit\" href=\"#jiff-makes-checked-or-saturating-arithmetic-explicit\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFor Jiff, whether you want to saturate or not is an explicit part of the API.\nAnd implementations of the \u003ccode\u003eAdd\u003c/code\u003e operator will panic on overflow:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use jiff::{Timestamp, ToSpan};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let ts = Timestamp::MAX;\n    assert!(ts.checked_add(1.day()).is_err());\n    assert_eq!(ts.saturating_add(1.hour())?, ts);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e jiff\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eTimestamp\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eToSpan\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e ts = \u003cspan class=\"pl-smi\"\u003eTimestamp\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eMAX\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ets\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003echecked_add\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eday\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003eis_err\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ets\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003esaturating_add\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e.\u003c/span\u003ehour\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e?\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e ts\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn contrast, \u003ccode\u003ehifitime\u003c/code\u003e appears to use saturating arithmetic everywhere (I've\nnot been able to find this behavior documented though, so I'm not clear on what\nthe intended semantics are):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-rust notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"use hifitime::{Duration, Epoch};\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let e1 = Epoch::from_unix_seconds(f64::MAX);\n    let e2 = e1 + Duration::from_days(1.0);\n    assert_eq!(e1, e2);\n\n    Ok(())\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003euse\u003c/span\u003e hifitime\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e \u003cspan class=\"pl-v\"\u003eEpoch\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n\u003cspan class=\"pl-k\"\u003efn\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emain\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e -\u0026gt; anyhow\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-smi\"\u003eResult\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-kos\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e e1 = \u003cspan class=\"pl-smi\"\u003eEpoch\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_unix_seconds\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ef64\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-v\"\u003eMAX\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003elet\u003c/span\u003e e2 = e1 + \u003cspan class=\"pl-smi\"\u003eDuration\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e::\u003c/span\u003e\u003cspan class=\"pl-en\"\u003efrom_days\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e1.0\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"pl-en\"\u003eassert_eq\u003c/span\u003e\u003cspan class=\"pl-en\"\u003e!\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003ee1\u003cspan class=\"pl-kos\"\u003e,\u003c/span\u003e e2\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"pl-en\"\u003eOk\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e(\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\u003cspan class=\"pl-kos\"\u003e)\u003c/span\u003e\n\u003cspan class=\"pl-kos\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\u003ca href=\"https://docs.rs/icu\" rel=\"nofollow\"\u003e\u003ccode\u003eicu\u003c/code\u003e\u003c/a\u003e (v1.5.0)\u003c/h2\u003e\u003ca id=\"user-content-icu-v150\" class=\"anchor\" aria-label=\"Permalink: icu (v1.5.0)\" href=\"#icu-v150\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe ICU4X project fulfils a slightly different need than \u003ccode\u003ejiff\u003c/code\u003e. Its main\nfeatures are calendrical calculations (\u003ccode\u003eicu::calendar\u003c/code\u003e), supporting conversions\nbetween different calendar systems such as Gregorian, Buddhist, Islamic,\nJapanese, etc., as well as localized datetime formatting (\u003ccode\u003eicu::datetime\u003c/code\u003e).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIt does not perform datetime or time-zone arithmetic, and does not have a\ntimestamp or duration type.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eicu\u003c/code\u003e can be used to complement \u003ccode\u003ejiff\u003c/code\u003e when localized date formatting or\ncalendar conversions are required. To facilitate this, the\n\u003ca href=\"https://docs.rs/jiff-icu\" rel=\"nofollow\"\u003e\u003ccode\u003ejiff-icu\u003c/code\u003e\u003c/a\u003e crate makes conversions between Jiff\nand ICU4X data types seamless. For example, to do localization starting from\na Jiff data type:\u003c/p\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"use icu::{\n    calendar::{japanese::Japanese, DateTime},\n    datetime::TypedDateTimeFormatter,\n    locid::locale,\n};\nuse jiff::Timestamp;\nuse jiff_icu::ConvertFrom as _;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let ts: Timestamp = \u0026quot;2024-09-10T23:37:20Z\u0026quot;.parse()?;\n    let zoned = ts.in_tz(\u0026quot;Asia/Tokyo\u0026quot;)?;\n\n    // Create ICU datetime.\n    let datetime = DateTime::convert_from(zoned.datetime());\n\n    // Convert to Japanese calendar.\n    let japanese_datetime = DateTime::new_from_iso(datetime, Japanese::new());\n\n    // Format for the en-GB locale.\n    let formatter = TypedDateTimeFormatter::try_new(\n        \u0026amp;locale!(\u0026quot;en-GB\u0026quot;).into(),\n        Default::default(),\n    )?;\n\n    // Assert that we get the expected result.\n    assert_eq!(\n        formatter.format(\u0026amp;japanese_datetime).to_string(),\n        \u0026quot;Sept 11, 6 Reiwa, 08:37:20\u0026quot;,\n    );\n\n    Ok(())\n}\"\u003e\u003cpre lang=\"text\" class=\"notranslate\"\u003e\u003ccode\u003euse icu::{\n    calendar::{japanese::Japanese, DateTime},\n    datetime::TypedDateTimeFormatter,\n    locid::locale,\n};\nuse jiff::Timestamp;\nuse jiff_icu::ConvertFrom as _;\n\nfn main() -\u0026gt; anyhow::Result\u0026lt;()\u0026gt; {\n    let ts: Timestamp = \"2024-09-10T23:37:20Z\".parse()?;\n    let zoned = ts.in_tz(\"Asia/Tokyo\")?;\n\n    // Create ICU datetime.\n    let datetime = DateTime::convert_from(zoned.datetime());\n\n    // Convert to Japanese calendar.\n    let japanese_datetime = DateTime::new_from_iso(datetime, Japanese::new());\n\n    // Format for the en-GB locale.\n    let formatter = TypedDateTimeFormatter::try_new(\n        \u0026amp;locale!(\"en-GB\").into(),\n        Default::default(),\n    )?;\n\n    // Assert that we get the expected result.\n    assert_eq!(\n        formatter.format(\u0026amp;japanese_datetime).to_string(),\n        \"Sept 11, 6 Reiwa, 08:37:20\",\n    );\n\n    Ok(())\n}\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe above example requires the following dependency specifications:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-toml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"anyhow = \u0026quot;1.0.81\u0026quot;\nicu = { version = \u0026quot;1.5.0\u0026quot;, features = [\u0026quot;std\u0026quot;] }\njiff = { version = \u0026quot;0.1.0\u0026quot;, features = [\u0026quot;serde\u0026quot;] }\njiff-icu = { version = \u0026quot;0.1.0\u0026quot; }\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eanyhow\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.0.81\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003eicu\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e1.5.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003estd\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003ejiff\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.1.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003efeatures\u003c/span\u003e = [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eserde\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e] }\n\u003cspan class=\"pl-smi\"\u003ejiff-icu\u003c/span\u003e = { \u003cspan class=\"pl-smi\"\u003eversion\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e0.1.0\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e }\u003c/pre\u003e\u003c/div\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"Comparison with other Rust datetime crates","fully_qualified_name":"Comparison with other Rust datetime crates","kind":"section_1","ident_start":2,"ident_end":44,"extent_start":0,"extent_end":56820,"ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":44}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":1278,"utf16_col":0}}},{"name":"[`chrono`](https://docs.rs/chrono) (v0.4.38)","fully_qualified_name":"[`chrono`](https://docs.rs/chrono) (v0.4.38)","kind":"section_2","ident_start":1797,"ident_end":1841,"extent_start":1794,"extent_end":33912,"ident_utf16":{"start":{"line_number":32,"utf16_col":3},"end":{"line_number":32,"utf16_col":47}},"extent_utf16":{"start":{"line_number":32,"utf16_col":0},"end":{"line_number":733,"utf16_col":0}}},{"name":"Time zone database integration","fully_qualified_name":"Time zone database integration","kind":"section_3","ident_start":2281,"ident_end":2311,"extent_start":2277,"extent_end":5064,"ident_utf16":{"start":{"line_number":50,"utf16_col":4},"end":{"line_number":50,"utf16_col":34}},"extent_utf16":{"start":{"line_number":50,"utf16_col":0},"end":{"line_number":129,"utf16_col":0}}},{"name":"Jiff losslessly roundtrips time zone aware datetimes","fully_qualified_name":"Jiff losslessly roundtrips time zone aware datetimes","kind":"section_3","ident_start":5068,"ident_end":5120,"extent_start":5064,"extent_end":9691,"ident_utf16":{"start":{"line_number":129,"utf16_col":4},"end":{"line_number":129,"utf16_col":56}},"extent_utf16":{"start":{"line_number":129,"utf16_col":0},"end":{"line_number":245,"utf16_col":0}}},{"name":"Jiff provides support for zone aware calendar arithmetic","fully_qualified_name":"Jiff provides support for zone aware calendar arithmetic","kind":"section_3","ident_start":9695,"ident_end":9751,"extent_start":9691,"extent_end":12587,"ident_utf16":{"start":{"line_number":245,"utf16_col":4},"end":{"line_number":245,"utf16_col":60}},"extent_utf16":{"start":{"line_number":245,"utf16_col":0},"end":{"line_number":318,"utf16_col":0}}},{"name":"Jiff losslessly roundtrips durations","fully_qualified_name":"Jiff losslessly roundtrips durations","kind":"section_3","ident_start":12591,"ident_end":12627,"extent_start":12587,"extent_end":13275,"ident_utf16":{"start":{"line_number":318,"utf16_col":4},"end":{"line_number":318,"utf16_col":40}},"extent_utf16":{"start":{"line_number":318,"utf16_col":0},"end":{"line_number":343,"utf16_col":0}}},{"name":"Jiff supports dealing with gaps in civil time","fully_qualified_name":"Jiff supports dealing with gaps in civil time","kind":"section_3","ident_start":13279,"ident_end":13324,"extent_start":13275,"extent_end":15581,"ident_utf16":{"start":{"line_number":343,"utf16_col":4},"end":{"line_number":343,"utf16_col":49}},"extent_utf16":{"start":{"line_number":343,"utf16_col":0},"end":{"line_number":405,"utf16_col":0}}},{"name":"Jiff supports rounding durations","fully_qualified_name":"Jiff supports rounding durations","kind":"section_3","ident_start":15585,"ident_end":15617,"extent_start":15581,"extent_end":16752,"ident_utf16":{"start":{"line_number":405,"utf16_col":4},"end":{"line_number":405,"utf16_col":36}},"extent_utf16":{"start":{"line_number":405,"utf16_col":0},"end":{"line_number":435,"utf16_col":0}}},{"name":"Jiff supports zone-aware rounding of durations","fully_qualified_name":"Jiff supports zone-aware rounding of durations","kind":"section_3","ident_start":16756,"ident_end":16802,"extent_start":16752,"extent_end":18003,"ident_utf16":{"start":{"line_number":435,"utf16_col":4},"end":{"line_number":435,"utf16_col":50}},"extent_utf16":{"start":{"line_number":435,"utf16_col":0},"end":{"line_number":470,"utf16_col":0}}},{"name":"Jiff supports re-balancing durations","fully_qualified_name":"Jiff supports re-balancing durations","kind":"section_3","ident_start":18007,"ident_end":18043,"extent_start":18003,"extent_end":18660,"ident_utf16":{"start":{"line_number":470,"utf16_col":4},"end":{"line_number":470,"utf16_col":40}},"extent_utf16":{"start":{"line_number":470,"utf16_col":0},"end":{"line_number":492,"utf16_col":0}}},{"name":"Jiff supports getting the `nth` weekday from the current date","fully_qualified_name":"Jiff supports getting the `nth` weekday from the current date","kind":"section_3","ident_start":18664,"ident_end":18725,"extent_start":18660,"extent_end":19387,"ident_utf16":{"start":{"line_number":492,"utf16_col":4},"end":{"line_number":492,"utf16_col":65}},"extent_utf16":{"start":{"line_number":492,"utf16_col":0},"end":{"line_number":516,"utf16_col":0}}},{"name":"Jiff supports detecting time zone offset conflicts","fully_qualified_name":"Jiff supports detecting time zone offset conflicts","kind":"section_3","ident_start":19391,"ident_end":19441,"extent_start":19387,"extent_end":22345,"ident_utf16":{"start":{"line_number":516,"utf16_col":4},"end":{"line_number":516,"utf16_col":54}},"extent_utf16":{"start":{"line_number":516,"utf16_col":0},"end":{"line_number":579,"utf16_col":0}}},{"name":"Jiff supports adding durations with calendar units","fully_qualified_name":"Jiff supports adding durations with calendar units","kind":"section_3","ident_start":22349,"ident_end":22399,"extent_start":22345,"extent_end":23155,"ident_utf16":{"start":{"line_number":579,"utf16_col":4},"end":{"line_number":579,"utf16_col":54}},"extent_utf16":{"start":{"line_number":579,"utf16_col":0},"end":{"line_number":602,"utf16_col":0}}},{"name":"Jiff supports zone-aware re-balancing of durations","fully_qualified_name":"Jiff supports zone-aware re-balancing of durations","kind":"section_3","ident_start":23159,"ident_end":23209,"extent_start":23155,"extent_end":24586,"ident_utf16":{"start":{"line_number":602,"utf16_col":4},"end":{"line_number":602,"utf16_col":54}},"extent_utf16":{"start":{"line_number":602,"utf16_col":0},"end":{"line_number":650,"utf16_col":0}}},{"name":"Jiff is generally faster than Chrono","fully_qualified_name":"Jiff is generally faster than Chrono","kind":"section_3","ident_start":24590,"ident_end":24626,"extent_start":24586,"extent_end":33912,"ident_utf16":{"start":{"line_number":650,"utf16_col":4},"end":{"line_number":650,"utf16_col":40}},"extent_utf16":{"start":{"line_number":650,"utf16_col":0},"end":{"line_number":733,"utf16_col":0}}},{"name":"[`time`](https://docs.rs/time) (v0.3.36)","fully_qualified_name":"[`time`](https://docs.rs/time) (v0.3.36)","kind":"section_2","ident_start":33915,"ident_end":33955,"extent_start":33912,"extent_end":51820,"ident_utf16":{"start":{"line_number":733,"utf16_col":3},"end":{"line_number":733,"utf16_col":43}},"extent_utf16":{"start":{"line_number":733,"utf16_col":0},"end":{"line_number":1117,"utf16_col":0}}},{"name":"Time zone database integration","fully_qualified_name":"Time zone database integration","kind":"section_3","ident_start":34368,"ident_end":34398,"extent_start":34364,"extent_end":37691,"ident_utf16":{"start":{"line_number":748,"utf16_col":4},"end":{"line_number":748,"utf16_col":34}},"extent_utf16":{"start":{"line_number":748,"utf16_col":0},"end":{"line_number":834,"utf16_col":0}}},{"name":"`time` supports its own custom format description","fully_qualified_name":"`time` supports its own custom format description","kind":"section_3","ident_start":37695,"ident_end":37744,"extent_start":37691,"extent_end":39048,"ident_utf16":{"start":{"line_number":834,"utf16_col":4},"end":{"line_number":834,"utf16_col":53}},"extent_utf16":{"start":{"line_number":834,"utf16_col":0},"end":{"line_number":887,"utf16_col":0}}},{"name":"Jiff supports rounding datetimes","fully_qualified_name":"Jiff supports rounding datetimes","kind":"section_3","ident_start":39052,"ident_end":39084,"extent_start":39048,"extent_end":40420,"ident_utf16":{"start":{"line_number":887,"utf16_col":4},"end":{"line_number":887,"utf16_col":36}},"extent_utf16":{"start":{"line_number":887,"utf16_col":0},"end":{"line_number":930,"utf16_col":0}}},{"name":"Jiff supports rounding durations","fully_qualified_name":"Jiff supports rounding durations","kind":"section_3","ident_start":40424,"ident_end":40456,"extent_start":40420,"extent_end":41108,"ident_utf16":{"start":{"line_number":930,"utf16_col":4},"end":{"line_number":930,"utf16_col":36}},"extent_utf16":{"start":{"line_number":930,"utf16_col":0},"end":{"line_number":954,"utf16_col":0}}},{"name":"Jiff provides support for calendar arithmetic","fully_qualified_name":"Jiff provides support for calendar arithmetic","kind":"section_3","ident_start":41112,"ident_end":41157,"extent_start":41108,"extent_end":41756,"ident_utf16":{"start":{"line_number":954,"utf16_col":4},"end":{"line_number":954,"utf16_col":49}},"extent_utf16":{"start":{"line_number":954,"utf16_col":0},"end":{"line_number":974,"utf16_col":0}}},{"name":"Jiff supports conveniently re-balancing durations","fully_qualified_name":"Jiff supports conveniently re-balancing durations","kind":"section_3","ident_start":41760,"ident_end":41809,"extent_start":41756,"extent_end":43642,"ident_utf16":{"start":{"line_number":974,"utf16_col":4},"end":{"line_number":974,"utf16_col":53}},"extent_utf16":{"start":{"line_number":974,"utf16_col":0},"end":{"line_number":1042,"utf16_col":0}}},{"name":"Jiff is generally faster than `time`","fully_qualified_name":"Jiff is generally faster than `time`","kind":"section_3","ident_start":43646,"ident_end":43682,"extent_start":43642,"extent_end":51820,"ident_utf16":{"start":{"line_number":1042,"utf16_col":4},"end":{"line_number":1042,"utf16_col":40}},"extent_utf16":{"start":{"line_number":1042,"utf16_col":0},"end":{"line_number":1117,"utf16_col":0}}},{"name":"[`hifitime`](https://docs.rs/hifitime) (v3.9.0)","fully_qualified_name":"[`hifitime`](https://docs.rs/hifitime) (v3.9.0)","kind":"section_2","ident_start":51823,"ident_end":51870,"extent_start":51820,"extent_end":54972,"ident_utf16":{"start":{"line_number":1117,"utf16_col":3},"end":{"line_number":1117,"utf16_col":50}},"extent_utf16":{"start":{"line_number":1117,"utf16_col":0},"end":{"line_number":1219,"utf16_col":0}}},{"name":"Time zone database integration","fully_qualified_name":"Time zone database integration","kind":"section_3","ident_start":52389,"ident_end":52419,"extent_start":52385,"extent_end":52858,"ident_utf16":{"start":{"line_number":1133,"utf16_col":4},"end":{"line_number":1133,"utf16_col":34}},"extent_utf16":{"start":{"line_number":1133,"utf16_col":0},"end":{"line_number":1142,"utf16_col":0}}},{"name":"`hifitime` supports leap seconds","fully_qualified_name":"`hifitime` supports leap seconds","kind":"section_3","ident_start":52862,"ident_end":52894,"extent_start":52858,"extent_end":54149,"ident_utf16":{"start":{"line_number":1142,"utf16_col":4},"end":{"line_number":1142,"utf16_col":36}},"extent_utf16":{"start":{"line_number":1142,"utf16_col":0},"end":{"line_number":1185,"utf16_col":0}}},{"name":"Jiff makes checked or saturating arithmetic explicit","fully_qualified_name":"Jiff makes checked or saturating arithmetic explicit","kind":"section_3","ident_start":54153,"ident_end":54205,"extent_start":54149,"extent_end":54972,"ident_utf16":{"start":{"line_number":1185,"utf16_col":4},"end":{"line_number":1185,"utf16_col":56}},"extent_utf16":{"start":{"line_number":1185,"utf16_col":0},"end":{"line_number":1219,"utf16_col":0}}},{"name":"[`icu`](https://docs.rs/icu) (v1.5.0)","fully_qualified_name":"[`icu`](https://docs.rs/icu) (v1.5.0)","kind":"section_2","ident_start":54975,"ident_end":55012,"extent_start":54972,"extent_end":56820,"ident_utf16":{"start":{"line_number":1219,"utf16_col":3},"end":{"line_number":1219,"utf16_col":40}},"extent_utf16":{"start":{"line_number":1219,"utf16_col":0},"end":{"line_number":1278,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":1315094102,"defaultBranch":"master","name":"jiff","ownerLogin":"jif-oai","currentUserCanPush":false,"isFork":true,"isEmpty":false,"createdAt":"2026-07-28T14:45:11.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/230027070?v=4","public":true,"private":false,"isOrgOwned":false,"isArchived":false},"currentUser":null,"uploadToken":"W8xMuJZM3QPDF-i06z8dDuAiVfWsUZreitqsVvwquokxIYtgoez6OdWPQbv3nr49zYGsqo-Wv9MaExFJ2pKbFQ","allShortcutsEnabled":false,"treeExpanded":true,"path":"COMPARE.md","symbolsExpanded":false,"refInfo":{"name":"master","listCacheKey":"v0:1785250152.0","canEdit":false,"currentOid":"2584cff71daebd477afe241cf049d4ccf595b855"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"":{"items":[{"name":".devcontainer","path":".devcontainer","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":".vim","path":".vim","contentType":"directory"},{"name":"bench","path":"bench","contentType":"directory"},{"name":"crates","path":"crates","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"fuzz","path":"fuzz","contentType":"directory"},{"name":"scripts","path":"scripts","contentType":"directory"},{"name":"testprograms","path":"testprograms","contentType":"directory"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".nvim.lua","path":".nvim.lua","contentType":"file"},{"name":".rgignore","path":".rgignore","contentType":"file"},{"name":"AI_POLICY.md","path":"AI_POLICY.md","contentType":"file"},{"name":"CHANGELOG.md","path":"CHANGELOG.md","contentType":"file"},{"name":"COMPARE.md","path":"COMPARE.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"COPYING","path":"COPYING","contentType":"file"},{"name":"Cargo.toml","path":"Cargo.toml","contentType":"file"},{"name":"Cross.toml","path":"Cross.toml","contentType":"file"},{"name":"DESIGN.md","path":"DESIGN.md","contentType":"file"},{"name":"LICENSE-MIT","path":"LICENSE-MIT","contentType":"file"},{"name":"PLATFORM.md","path":"PLATFORM.md","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"UNLICENSE","path":"UNLICENSE","contentType":"file"},{"name":"rustfmt.toml","path":"rustfmt.toml","contentType":"file"}],"totalCount":25}},"fileTreeProcessingTime":18.413031999999998,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"master","listCacheKey":"v0:1785250152.0","canEdit":false,"refType":"branch","currentOid":"2584cff71daebd477afe241cf049d4ccf595b855","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"COMPARE.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/jif-oai/jiff/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"COMPARE.md","displayUrl":"https://github.com/jif-oai/jiff/blob/master/COMPARE.md?raw=true","headerInfo":{"blobSize":"55.5 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"b461ba5","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fjif-oai%2Fjiff%2Fblob%2Fmaster%2FCOMPARE.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"1278","truncatedSloc":"1017"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/jif-oai/jiff/blob/master/COMPARE.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/jif-oai/jiff/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/jif-oai/jiff/raw/refs/heads/master/COMPARE.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["# Comparison with other Rust datetime crates","","This document is meant to be a comparison between Jiff and each of the other","prominent open source datetime libraries for Rust. If you feel like there is a","library missing from this list, please file an issue about it. I would prefer","to only add libraries to this list that are being used in production or have a","substantial number of users.","","The goal of this document is to be as _descriptive_ and _substantively","complete_ as possible. For example, \"Chrono has a better API design than Jiff\"","would be a pretty vague value judgment that someone could easily disagree with.","But, \"Chrono allows using a zone-aware datetime type that is `Copy` while Jiff","does not\" would be a factual comparison that someone might use to _support_ an","opinion that Chrono's API design is better than Jiff's. In other words, this","document should provide the \"facts of comparison\" but refrain from assigning","value judgments.","","In terms of completeness, it is probably not realistic to expect 100%","completion here. We aren't hunting for Korok Seeds. Instead, this document","aims for _substantive_ completion. That is, if there's a point of difference","between Jiff and another library that would likely influence someone's decision","of which library to use, and can be articulated descriptively, then it should","probably be in this document.","","The current status of this document is that it is both _incomplete_ and","_biased_. That is, this first draft was written by the author of Jiff without","any input from other crate maintainers. (To other crate maintainers: I welcome","feedback. Even if it's just filing an issue.)","","Note that this document contains many code snippets. They can be tested with","`cargo test --doc _documentation::comparison` from the root of this repository.","","## [`chrono`](https://docs.rs/chrono) (v0.4.38)","","Chrono is a Rust datetime library that provides a time zone aware datetime","type.","","For the following comparisons, a `Cargo.toml` with the following dependencies","should be able to run any of the programs in this section:","","```toml","anyhow = \"1.0.81\"","chrono = \"0.4.38\"","chrono-tz = { version = \"0.9.0\", features = [\"serde\"] }","jiff = { version = \"0.2.0\", features = [\"serde\"] }","serde = \"1.0.203\"","serde_json = \"1.0.117\"","tzfile = \"0.1.3\"","```","","### Time zone database integration","","Jiff gives you automatic integration with your copy of the Time Zone Database.","On Unix, it's usually found at `/usr/share/zoneinfo`. On Windows, since there","is no canonical location, Jiff will depend on `jiff-tzdb` by default, which","will embed the entire database into your binary. Jiff hides these details from","you. For example, to convert a civil time into an absolute time in a particular","time zone:","","```rust","use jiff::civil::date;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = date(2024, 6, 30).at(9, 46, 0, 0).in_tz(\"America/New_York\")?;","    assert_eq!(zdt.to_string(), \"2024-06-30T09:46:00-04:00[America/New_York]\");","    Ok(())","}","```","","For Chrono, one recommended option is to use the","[`chrono-tz`](https://docs.rs/chrono-tz) crate:","","```rust","use anyhow::Context;","use chrono::TimeZone;","use chrono_tz::America::New_York;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = New_York.with_ymd_and_hms(2024, 6, 30, 9, 46, 0)","        .single()","        .context(\"invalid naive time\")?;","    assert_eq!(zdt.to_string(), \"2024-06-30 09:46:00 EDT\");","    Ok(())","}","```","","`chrono-tz` works by embedding an entire copy of the Time Zone Database into","your binary, where each time zone is represented as a Rust value that can be","imported via `use`. A disadvantage of this approach is that you're reliant on","`chrono-tz` updates to get the most recent time zone information. An advantage","of this approach is that you never need to worry about an end user's system","state. Another advantage is that this allows a `TimeZone` trait implementation","to be `Copy` via a `\u0026Tz`, and that in turn allows a `chrono::DateTime` to be","`Copy`. In contrast, in Jiff, a `TimeZone` is never `Copy`. Since a `Zoned`","embeds a `TimeZone`, a `Zoned` is never `Copy` either.","","Another recommended option is the [`tzfile`](https://docs.rs/tzfile) crate.","Unlike `chrono-tz`, the `tzfile` crate will try to read time zone data from","your system's copy of the Time Zone Database.","","```rust","use anyhow::Context;","use chrono::TimeZone;","use tzfile::Tz;","","#[cfg(unix)]","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let tz = Tz::named(\"America/New_York\")?;","    let zdt = (\u0026tz).with_ymd_and_hms(2024, 6, 30, 9, 46, 0)","        .single()","        .context(\"invalid naive time\")?;","    assert_eq!(zdt.to_string(), \"2024-06-30 09:46:00 EDT\");","    Ok(())","}","","// `tzfile` exposes a platform specific API, which means","// users of the crate have to deal with platform differences","// themselves.","#[cfg(not(unix))]","fn main() -\u003e anyhow::Result\u003c()\u003e {","    Ok(())","}","```","","Note though that at time of writing (2024-07-11), `tzfile::Tz::named` will","read and parse the corresponding time zone rules from disk on every call.","Conversely, in Jiff, all time zone lookups by name are cached. This may or may","not matter for your use case.","","### Jiff losslessly roundtrips time zone aware datetimes","","In Jiff, with `serde` support enabled, one can serialize and deserialize a","`Zoned` value losslessly. This means that, after deserialization, you can","expect it to still perform DST arithmetic:","","```rust","use jiff::{civil::date, ToSpan, Zoned};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = date(2024, 3, 10).at(1, 59, 59, 0).in_tz(\"America/New_York\")?;","","    let json = serde_json::to_string_pretty(\u0026zdt)?;","    assert_eq!(json, \"\\\"2024-03-10T01:59:59-05:00[America/New_York]\\\"\");","","    let got: Zoned = serde_json::from_str(\u0026json)?;","    assert_eq!(got.to_string(), \"2024-03-10T01:59:59-05:00[America/New_York]\");","    let next = got.checked_add(1.minute())?;","    assert_eq!(next.to_string(), \"2024-03-10T03:00:59-04:00[America/New_York]\");","","    Ok(())","}","```","","Notice that when we add a minute, it jumps to `03:00` civil time because of the","transition into daylight saving time in my selected time zone. Notice also the","offset change from `-05` to `-04`.","","Compare this with Chrono which also supports `serde`, but not with `chrono-tz`","or `tzfile`. One option is to use its `Local` implementation of its `TimeZone`","trait:","","```rust,no_run","use anyhow::Context;","use chrono::{DateTime, FixedOffset, Local, TimeDelta, TimeZone};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = Local.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)","        .single()","        .context(\"invalid naive time\")?;","","    let json = serde_json::to_string_pretty(\u0026zdt)?;","    // Chrono only serializes the offset, which makes lossless","    // deserialization impossible. Chrono loses the time zone","    // information.","    assert_eq!(json, \"\\\"2024-03-10T01:59:59-05:00\\\"\");","","    // The serialized datetime has no time zone information,","    // so unless there is some out-of-band information saying","    // what its time zone is, we're forced to use a fixed offset:","    let got: DateTime\u003cFixedOffset\u003e = serde_json::from_str(\u0026json)?;","    assert_eq!(got.to_string(), \"2024-03-10 01:59:59 -05:00\");","    let next = got.checked_add_signed(TimeDelta::minutes(1))","        .context(\"arithmetic failed\")?;","    // This is correct for fixed offset, but it's no longer","    // DST aware.","    assert_eq!(next.to_string(), \"2024-03-10 02:00:59 -05:00\");","","    // We could deserialize into a `DateTime\u003cLocal\u003e`, but this","    // requires knowing that the time zone of the datetime matches","    // local time zone. Which you might know. But you might not.","    let got: DateTime\u003cLocal\u003e = serde_json::from_str(\u0026json)?;","    assert_eq!(got.to_string(), \"2024-03-10 01:59:59 -05:00\");","    let next = got.checked_add_signed(TimeDelta::minutes(1))","        .context(\"arithmetic failed\")?;","    assert_eq!(next.to_string(), \"2024-03-10 03:00:59 -04:00\");","","    Ok(())","}","```","","Or, if you have a `Tz` from `chrono-tz`. But in this case, since `chrono-tz`","doesn't support Serde, you have to convert to a `DateTime\u003cFixedOffset\u003e`. Like","above, you'll lose DST safe arithmetic after deserialization:","","```rust","use anyhow::Context;","use chrono::{DateTime, FixedOffset, TimeDelta, TimeZone};","use chrono_tz::America::New_York;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = New_York.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)","        .single()","        .context(\"invalid naive time\")?;","","    let json = serde_json::to_string_pretty(\u0026zdt.fixed_offset())?;","    // Chrono only serializes the offset, which makes lossless","    // deserialization impossible. Chrono loses the time zone","    // information.","    assert_eq!(json, \"\\\"2024-03-10T01:59:59-05:00\\\"\");","","    // The serialized datetime has no time zone information,","    // so unless there is some out-of-band information saying","    // what its time zone is, we're forced to use a fixed offset:","    let got: DateTime\u003cFixedOffset\u003e = serde_json::from_str(\u0026json)?;","    assert_eq!(got.to_string(), \"2024-03-10 01:59:59 -05:00\");","    let next = got.checked_add_signed(TimeDelta::minutes(1))","        .context(\"arithmetic failed\")?;","    // This is correct for fixed offset, but it's no longer","    // DST aware.","    assert_eq!(next.to_string(), \"2024-03-10 02:00:59 -05:00\");","","    Ok(())","}","```","","The main way to solve this problem (and is how `java.time`, Temporal and Jiff","solve it), is by supporting [RFC 9557]. Otherwise, the only way to fully","capture Jiff's functionality in Chrono is to define a custom serialization","format that includes the instant, the time zone identifier *and* the offset.","(The offset is used for conflict resolution when deserializing datetimes made","in the future for which their offset has changed due to changes in the time","zone database.)","","[RFC 9557]: https://datatracker.ietf.org/doc/rfc9557/","","### Jiff provides support for zone aware calendar arithmetic","","With Jiff, you can add non-uniform units like days to time zone aware datetimes,","and get non-uniform units like days as a representation of a span between","datetimes. And they agree on the results.","","```rust","use jiff::{civil::date, ToSpan, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = zdt1.checked_add(1.day())?;","","    // Even though 2 o'clock didn't occur on 2024-03-10, adding 1 day","    // returns the same civil time the next day.","    assert_eq!(zdt2.to_string(), \"2024-03-10T21:00:00-04:00[America/New_York]\");","    // The span of time is 23 hours:","    assert_eq!(\u0026zdt2 - \u0026zdt1, 23.hours().fieldwise());","    // But if you ask for the span in units of days, you get exactly 1:","    assert_eq!(zdt1.until((Unit::Day, \u0026zdt2))?, 1.day().fieldwise());","","    Ok(())","}","```","","This is important and difficult to get right because some days are only 23","hours long (typically the day of the year where DST starts) and some days are","25 hours long (typically the day of the year where DST ends). With Jiff, you","can seamlessly go back-and-forth between calendar units and clock units without","worrying about whether \"day\" will be interpreted differently.","","Chrono has some support for this. Namely, it can add units of days in a time","zone aware fashion, but it cannot produce spans of time involving days between","two zone aware datetimes that is consistent with adding days.","","```rust","use anyhow::Context;","use chrono::{Days, TimeDelta, TimeZone};","use chrono_tz::America::New_York;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = New_York.with_ymd_and_hms(2024, 3, 9, 21, 0, 0)","        .single()","        .context(\"invalid naive time\")?;","","    // Adding 1 day via TimeDelta leads to a result that is","    // 24 hours later, including the gap at 2am on 2024-03-10.","    // As a result, you get a different civil time, which is","    // usually not what is intended.","    let zdt2 = zdt1.checked_add_signed(TimeDelta::days(1))","        .context(\"adding a time delta failed\")?;","    assert_eq!(zdt2.to_string(), \"2024-03-10 22:00:00 EDT\");","","    // However, Chrono does expose a separate API for adding","    // units of days specifically. This does get you the","    // correct result.","    let zdt2 = zdt1.checked_add_days(Days::new(1))","        .context(\"adding days failed\")?;","    assert_eq!(zdt2.to_string(), \"2024-03-10 21:00:00 EDT\");","","    // The only way to compute a duration between two datetimes","    // in Chrono is with a `TimeDelta`:","    let delta = zdt2.signed_duration_since(\u0026zdt1);","    // And since `TimeDelta` assumes all days are exactly 24","    // hours long, you get a result of `0` days. If this were","    // a fold, the number of days would be `1`, but you'd also","    // have a number of hours equal to `1`.","    assert_eq!(delta.num_days(), 0);","","    Ok(())","}","```","","### Jiff losslessly roundtrips durations","","Jiff implements something close to ISO 8601 to provide lossless serialization","and deserialization of its `Span` type. A `Span` covers both calendar and clock","units.","","```rust","use jiff::{Span, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let span = 5.years().months(2).days(1).hours(20);","    let json = serde_json::to_string_pretty(\u0026span)?;","    assert_eq!(json, \"\\\"P5Y2M1DT20H\\\"\");","","    let got: Span = serde_json::from_str(\u0026json)?;","    assert_eq!(got, span.fieldwise());","","    Ok(())","}","```","","Chrono [does not currently have Serde support for its duration type][serde-duration].","","[serde-duration]: https://github.com/chronotope/chrono/issues/117","","### Jiff supports dealing with gaps in civil time","","A gap in civil time most typically occurs when a particular region enters","daylight saving time. When this happens, some time on the clocks in that region","is skipped. It never appears. (A fold happens when the clocks are rolled back,","usually when leaving daylight saving time. In this case, some time on the clock","is repeated.)","","Jiff supports automatically selecting a \"reasonable\" choice in either case","via its \"compatible\" strategy (as specified by [RFC 5545]).","","```rust","use jiff::Zoned;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // This is a gap. The default strategy takes the time after the gap.","    let zdt: Zoned = \"2024-03-10 02:30[America/New_York]\".parse()?;","    assert_eq!(zdt.to_string(), \"2024-03-10T03:30:00-04:00[America/New_York]\");","","    // This is a fold. The default strategy takes the time before the fold.","    let zdt: Zoned = \"2024-11-03 01:30[America/New_York]\".parse()?;","    // The time after the fold would be identical,","    // except the offset would be -05.","    assert_eq!(zdt.to_string(), \"2024-11-03T01:30:00-04:00[America/New_York]\");","","    Ok(())","}","```","","Jiff also exposes all information available with respect to ambiguous civil","datetimes via `tz::AmbiguousZoned`, `tz::AmbiguousTimestamp` and","`tz::AmbiguousOffset`. This enables callers to implement whatever strategy","they want.","","While Chrono will let you deal with folds, it returns `MappedLocalTime::None`","in the case of a gap with no additional information. So there's really nothing","else you can conveniently do in this case except return an error:","","```rust","use anyhow::Context;","use chrono::{offset::MappedLocalTime, TimeZone};","use chrono_tz::America::New_York;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // For gaps, Chrono exposes no additional information.","    let mapped = New_York.with_ymd_and_hms(2024, 3, 10, 2, 30, 0);","    assert_eq!(mapped, MappedLocalTime::None);","","    // For folds, Chrono gives you the two choices.","    // This is approximately equivalent to what Jiff exposes","    // in the case of a fold.","    let zdt = New_York.with_ymd_and_hms(2024, 11, 3, 1, 30, 0)","        .earliest()","        .context(\"invalid datetime\")?;","    assert_eq!(zdt.to_string(), \"2024-11-03 01:30:00 EDT\");","","    Ok(())","}","```","","[RFC 5545]: https://datatracker.ietf.org/doc/html/rfc5545","","### Jiff supports rounding durations","","In Jiff, one can round the duration computed between two datetimes:","","```rust","use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\"America/New_York\")?;","","    let round_options = ZonedDifference::new(\u0026zdt2)","        .largest(Unit::Year)","        .smallest(Unit::Day)","        .mode(RoundMode::HalfExpand);","    let span = zdt1.until(round_options)?;","    assert_eq!(span.fieldwise(), 22.years().months(7).days(24));","","    Ok(())","}","```","","While Chrono supports rounding datetimes themselves via its","`chrono::duration::DurationRound` trait, it does not support rounding durations","themselves. Indeed, its principle duration type, `TimeDelta`, is an \"absolute\"","duration like `std::time::Duration` (except that it is signed). It doesn't keep","track of individual units like Jiff does. Instead, everything gets normalized","into a 96-bit integer number of nanoseconds. With this representation, it is","impossible to do DST safe rounding to non-uniform units like days.","","### Jiff supports zone-aware rounding of durations","","Jiff's duration rounding is time zone aware. For example, if you're rounding to","a number of days, it knows to round 11.5 hours up to 1 day on days with gaps,","and round 12 hours down to 0 days on days with folds. The only requirement","is that we provide a reference datetime with which to interpret the span.","","```rust","use jiff::{civil::date, SpanRound, ToSpan, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let gapday = date(2024, 3, 10).in_tz(\"America/New_York\")?;","    let foldday = date(2024, 11, 3).in_tz(\"America/New_York\")?;","","    let span1 = 11.hours().minutes(30);","    let span2 = span1.round(","        SpanRound::new().smallest(Unit::Day).relative(\u0026gapday),","    )?;","    // rounds up, even though on a normal day 11.5 hours would round down.","    assert_eq!(span2, 1.day().fieldwise());","","    let span1 = 12.hours();","    let span2 = span1.round(","        SpanRound::new().smallest(Unit::Day).relative(\u0026foldday),","    )?;","    // rounds down, even though on a normal day 12 hours would round up.","    assert_eq!(span2, 0.days().fieldwise());","","    Ok(())","}","```","","As with the previous section, Chrono does not support rounding durations or","rounding units like `Days` with respect to a reference datetime.","","### Jiff supports re-balancing durations","","This example is like the one above, except we choose a smaller \"largest\" unit:","","```rust","use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\"America/New_York\")?;","","    let round_options = ZonedDifference::new(\u0026zdt2)","        .largest(Unit::Month)","        .smallest(Unit::Day)","        .mode(RoundMode::HalfExpand);","    let span = zdt1.until(round_options)?;","    assert_eq!(span, 271.months().days(24).fieldwise());","","    Ok(())","}","```","","### Jiff supports getting the `nth` weekday from the current date","","```rust","use jiff::civil::{date, Weekday};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = date(2024, 7, 11).at(22, 59, 0, 0).in_tz(\"America/New_York\")?;","    assert_eq!(zdt.weekday(), Weekday::Thursday);","","    let next_tuesday = zdt.nth_weekday(1, Weekday::Tuesday)?;","    assert_eq!(","        next_tuesday.to_string(),","        \"2024-07-16T22:59:00-04:00[America/New_York]\",","    );","","    Ok(())","}","```","","Chrono does have `NaiveDate::from_weekday_of_month_opt`, but it only counts","the number of weekdays for a particular month. (The Jiff equivalent is","`nth_weekday_of_month`.) Moreover, Chrono's method is only available on naive","dates and not zone aware datetimes.","","### Jiff supports detecting time zone offset conflicts","","One of the problems with storing datetimes in the future is that time","zone rules can change. For example, if you stored the zone aware datetime","`2020-01-15T12:00-02[America/Sao_Paulo]` in 2018, then it would be considered","to be in daylight saving time with an offset of `-2`. However, in 2019,","daylight saving time was abolished in this time zone, which renders the","datetime invalid because its offset *should* be `-3`.","","Jiff can detect these sorts of conflicts and will actually return a parse error","by default. We exemplify this by creating and serializing a zoned datetime from","an old copy of the Time Zone Database, and then try to parse it back using our","system's current copy of the Time Zone Database. (This also demonstrate's Jiff","support for using multiple copies of the Time Zone Database simultaneously.","But the main point here is to simulate the process of \"serialize datetime,","time zone rules change, deserialize datetime.\")","","```rust,no_run","use jiff::{fmt::temporal::DateTimeParser, tz::{self, TimeZoneDatabase}};","","// We use a custom parser with a default configuration because we need","// to ask the parser to use a different time zone database than the","// default. This can't be done via the nice `\"...\".parse()` API one","// would typically use.","static PARSER: DateTimeParser = DateTimeParser::new();","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // Open a version of tzdb from before Brazil announced its abolition","    // of daylight saving time.","    let tzdb2018 = TimeZoneDatabase::from_dir(\"path/to/tzdb-2018b\")?;","    // Open the system tzdb.","    let tzdb = tz::db();","","    // Parse the same datetime string with the same parser, but using two","    // different versions of tzdb.","    let dt = \"2020-01-15T12:00[America/Sao_Paulo]\";","    let zdt2018 = PARSER.parse_zoned_with(\u0026tzdb2018, dt)?;","    let zdt = PARSER.parse_zoned_with(tzdb, dt)?;","","    // Before DST was abolished, 2020-01-15 was in DST, which corresponded","    // to UTC offset -02. Since DST rules applied to datetimes in the","    // future, the 2018 version of tzdb would lead one to interpret","    // 2020-01-15 as being in DST.","    assert_eq!(zdt2018.offset(), tz::offset(-2));","    // But DST was abolished in 2019, which means that 2020-01-15 was no","    // no longer in DST. So after a tzdb update, the same datetime as above","    // now has a different offset.","    assert_eq!(zdt.offset(), tz::offset(-3));","","    // So if you try to parse a datetime serialized from an older copy of","    // tzdb with a new copy of tzdb, you'll get an error under the default","    // configuration because of `OffsetConflict::Reject`. This would succeed if","    // you parsed it using tzdb2018!","    assert!(PARSER.parse_zoned_with(tzdb, zdt2018.to_string()).is_err());","","    Ok(())","}","```","","With Chrono, this sort of checking isn't possible in the first place because","it doesn't support an interchange format that includes the IANA time zone","identifier.","","### Jiff supports adding durations with calendar units","","Since `Span` is Jiff's single duration type that combines calendar and clock","units, one can freely add them together. The only requirement is that if a span","has calendar units, you need to provide a reference date. (Because 1 month from","April 1 is shorter than 1 month from May 1.)","","```rust","use jiff::{civil::date, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let span1 = 2.years().months(4).days(25).hours(23);","    let span2 = 3.hours();","    let span3 = span1.checked_add((span2, date(2024, 1, 1)))?;","    assert_eq!(span3.fieldwise(), 2.years().months(4).days(26).hours(2));","","    Ok(())","}","```","","While Chrono has types like `Months` and `Days`, there's no way to combine","them into one, and Chrono does not provide operations on both at the same time.","","### Jiff supports zone-aware re-balancing of durations","","If you have a span of `1.day()` and want to convert it to hours, then that","calculation depends on how long the day is. If you provide a civil date as","a relative reference point, then Jiff assumes the day is always 24 hours long:","","```rust","use jiff::{civil, SpanRound, ToSpan, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let relative = civil::date(2024, 4, 1);","    let span1 = 1.day();","    let span2 = span1.round(","        SpanRound::new().largest(Unit::Hour).relative(relative),","    )?;","    assert_eq!(span2, 24.hours().fieldwise());","","    Ok(())","}","```","","But if a reference date is provided with a time zone, then the re-balancing is","DST safe:","","```rust","use jiff::{civil::date, SpanRound, ToSpan, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // In the case of a gap (typically transitioning in DST):","    let zdt = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(\"America/New_York\")?;","    let span1 = 1.day();","    let span2 = span1.round(","        SpanRound::new().largest(Unit::Hour).relative(\u0026zdt)","    )?;","    assert_eq!(span2, 23.hours().fieldwise());","","    // In the case of a fold (typically transitioning out of DST):","    let zdt = date(2024, 11, 2).at(21, 0, 0, 0).in_tz(\"America/New_York\")?;","    let span1 = 1.day();","    let span2 = span1.round(","        SpanRound::new().largest(Unit::Hour).relative(\u0026zdt)","    )?;","    assert_eq!(span2, 25.hours().fieldwise());","","    Ok(())","}","```","","### Jiff is generally faster than Chrono","","There are some cases where Chrono is faster than Jiff, but Jiff should","generally be competitive for equivalent operations. It's generally not","possible for Chrono or Jiff to always be faster than the other, since","they each use different representations for fundamental types. This in turn","makes some operations faster and others slower, depending on what you're","trying to do. With that said, Jiff is uniformly faster than Chrono when it","comes to printing and parsing.","","```text","$ cd bench","$ cargo bench -- --save-baseline base","[.. snip ..]","$ critcmp base -g '(.*)/(?:jiff|chrono)$'","group                                                           baseline//chrono                       baseline//jiff","-----                                                           ----------------                       --------------","civil_datetime/add_days/diffyear/duration                       1.00      8.5±0.08ns        ? ?/sec    1.56     13.3±0.15ns        ? ?/sec","civil_datetime/add_days/diffyear/span                                                                  1.00     23.9±0.13ns        ? ?/sec","civil_datetime/add_days/sameyear/duration                       1.00      6.8±0.05ns        ? ?/sec    1.96     13.3±0.17ns        ? ?/sec","civil_datetime/add_days/sameyear/span                                                                  1.00     23.8±0.13ns        ? ?/sec","civil_datetime/to_timestamp_static/bundled                      2.05     22.3±0.24ns        ? ?/sec    1.00     10.9±0.14ns        ? ?/sec","civil_datetime/to_timestamp_static/zoneinfo                     1.53     16.2±0.15ns        ? ?/sec    1.00     10.6±0.09ns        ? ?/sec","civil_datetime/to_timestamp_tzdb_lookup/bundled                 1.00     32.0±0.15ns        ? ?/sec","civil_datetime/to_timestamp_tzdb_lookup/zoneinfo                45.85  1919.7±6.17ns        ? ?/sec    1.00     41.9±0.15ns        ? ?/sec","date/add_days/diffyear/duration                                 1.00      5.8±0.05ns        ? ?/sec    1.12      6.5±0.04ns        ? ?/sec","date/add_days/diffyear/span                                                                            1.00      6.5±0.04ns        ? ?/sec","date/add_days/one/duration                                      1.00      2.1±0.02ns        ? ?/sec    2.55      5.4±0.05ns        ? ?/sec","date/add_days/one/span                                                                                 1.00      5.8±0.02ns        ? ?/sec","date/add_days/sameyear/duration                                 1.00      2.1±0.01ns        ? ?/sec    3.08      6.5±0.05ns        ? ?/sec","date/add_days/sameyear/span                                                                            1.00      6.5±0.05ns        ? ?/sec","date/difference_days/duration                                   1.18      3.4±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec","date/difference_days/span                                                                              1.00      2.5±0.02ns        ? ?/sec","date/tomorrow/diff-month                                        1.00      0.4±0.00ns        ? ?/sec    3.25      1.3±0.01ns        ? ?/sec","date/tomorrow/diff-year                                         1.16      1.7±0.01ns        ? ?/sec    1.00      1.4±0.01ns        ? ?/sec","date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec    1.99      0.8±0.00ns        ? ?/sec","date/yesterday/diff-month                                       1.00      0.4±0.02ns        ? ?/sec    3.17      1.3±0.01ns        ? ?/sec","date/yesterday/diff-year                                        1.85      2.0±0.01ns        ? ?/sec    1.00      1.1±0.01ns        ? ?/sec","date/yesterday/same-month                                       1.00      0.4±0.03ns        ? ?/sec    1.72      0.7±0.02ns        ? ?/sec","parse/civil_datetime                                            2.95     73.6±0.72ns        ? ?/sec    1.00     24.9±0.19ns        ? ?/sec","parse/rfc2822                                                   3.09     59.9±0.30ns        ? ?/sec    1.00     19.3±0.17ns        ? ?/sec","parse/strptime/oneshot                                          3.11    197.8±0.80ns        ? ?/sec    1.00     63.6±1.19ns        ? ?/sec","parse/strptime/prebuilt                                         1.00     77.1±1.44ns        ? ?/sec","print/civil_datetime                                            13.10   147.4±0.60ns        ? ?/sec    1.00     11.3±0.04ns        ? ?/sec","print/iso8601_duration/long-time/duration/buffer                2.38     46.5±0.34ns        ? ?/sec    1.00     19.5±0.04ns        ? ?/sec","print/iso8601_duration/long-time/duration/to_string             3.13     71.7±0.36ns        ? ?/sec    1.00     23.0±0.07ns        ? ?/sec","print/iso8601_duration/short/duration/buffer                    2.65     32.3±0.30ns        ? ?/sec    1.00     12.2±0.04ns        ? ?/sec","print/iso8601_duration/short/duration/to_string                 2.08     36.8±0.33ns        ? ?/sec    1.00     17.7±0.05ns        ? ?/sec","print/iso8601_duration/tiny/duration/buffer                     2.74     31.6±0.32ns        ? ?/sec    1.00     11.6±0.03ns        ? ?/sec","print/iso8601_duration/tiny/duration/to_string                  2.28     36.5±0.40ns        ? ?/sec    1.00     16.0±0.08ns        ? ?/sec","print/rfc2822/buffer                                            4.91     64.6±0.59ns        ? ?/sec    1.00     13.2±0.03ns        ? ?/sec","print/rfc2822/to_string                                         5.75    111.0±0.37ns        ? ?/sec    1.00     19.3±0.05ns        ? ?/sec","print/rfc3339/buffer                                            3.79     64.2±0.56ns        ? ?/sec    1.00     17.0±0.14ns        ? ?/sec","print/rfc3339/to_string                                         4.75    112.4±0.33ns        ? ?/sec    1.00     23.6±0.11ns        ? ?/sec","print/rfc9557/buffer                                                                                   1.00     16.2±0.05ns        ? ?/sec","print/rfc9557/to_string                                                                                1.00     22.2±0.07ns        ? ?/sec","print/strftime/oneshot/buffer                                   3.90    213.9±1.99ns        ? ?/sec    1.00     54.8±0.32ns        ? ?/sec","print/strftime/oneshot/to_string                                3.63    261.3±1.26ns        ? ?/sec    1.00     72.1±0.49ns        ? ?/sec","print/strftime/oneshot/zoned                                                                           1.00     65.5±0.64ns        ? ?/sec","print/strftime/prebuilt/buffer                                  1.00     85.4±0.52ns        ? ?/sec","print/strftime/prebuilt/to_string                               1.00    147.4±0.76ns        ? ?/sec","timestamp/add_time_secs/duration                                2.42      6.1±0.08ns        ? ?/sec    1.00      2.5±0.03ns        ? ?/sec","timestamp/add_time_secs/span                                                                           1.00      3.8±0.06ns        ? ?/sec","timestamp/add_time_subsec/duration                              2.10      6.1±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec","timestamp/add_time_subsec/span                                                                         1.00      8.1±0.09ns        ? ?/sec","timestamp/every_hour_in_week/byhand                             16.15  1679.6±6.13ns        ? ?/sec    1.00    104.0±0.72ns        ? ?/sec","timestamp/every_hour_in_week/series                                                                    1.00    105.9±0.66ns        ? ?/sec","timestamp/from_seconds/integer                                  14.45     4.7±0.03ns        ? ?/sec    1.00      0.3±0.00ns        ? ?/sec","timestamp/to_civil_datetime_offset_conversion                   1.65      7.3±0.02ns        ? ?/sec    1.00      4.4±0.04ns        ? ?/sec","timestamp/to_civil_datetime_offset_holistic                                                            1.00      4.4±0.04ns        ? ?/sec","timestamp/to_civil_datetime_static/America-New-York/bundled     1.00     16.0±0.16ns        ? ?/sec","timestamp/to_civil_datetime_static/America-New-York/zoneinfo    1.42     18.4±0.11ns        ? ?/sec    1.00     13.0±0.11ns        ? ?/sec","timestamp/to_civil_datetime_static/Asia-Shanghai/bundled        1.00     15.2±0.16ns        ? ?/sec","timestamp/to_civil_datetime_static/Asia-Shanghai/zoneinfo       3.16     15.7±0.11ns        ? ?/sec    1.00      5.0±0.05ns        ? ?/sec","zoned/fixed_offset_add_time/duration                            1.00      6.1±0.06ns        ? ?/sec    1.56      9.5±0.05ns        ? ?/sec","zoned/fixed_offset_add_time/span                                                                       1.00     16.6±0.09ns        ? ?/sec","zoned/fixed_offset_to_civil_datetime                            1.23      5.6±0.01ns        ? ?/sec    1.00      4.5±0.01ns        ? ?/sec","zoned/fixed_offset_to_timestamp                                 3.15      1.2±0.01ns        ? ?/sec    1.00      0.4±0.00ns        ? ?/sec","```","","Questions about benchmarks are welcome in","[Discussions on GitHub](https://github.com/BurntSushi/jiff/discussions).","","## [`time`](https://docs.rs/time) (v0.3.36)","","`time` is a Rust datetime library that provides a time zone offset aware","datetime type.","","For the following comparisons, a `Cargo.toml` with the following dependencies","should be able to run any of the programs in this section:","","```toml","anyhow = \"1.0.81\"","jiff = { version = \"0.2.0\", features = [\"serde\"] }","time = { version = \"0.3.36\", features = [\"local-offset\", \"macros\", \"parsing\"] }","time-tz = \"2.0.0\"","```","","### Time zone database integration","","Like `chrono`, the `time` crate does not come with any out of the box","functionality for reading your system's copy of the Time Zone Database.","However, there is a third party crate, [`time-tz`](https://docs.rs/time-tz)","that provides some time zone support in a fashion similar to `chrono-tz`. That","is, it requires bundling the time zone data into your binary and does not","support reading the system copy of the Time Zone Database when available.","","Note also that `time` does not provide the extension points necessary in its API","to make handling time zone aware datetimes ergonomic. Indeed, many operations","are not expressible at all.","","The main thing `time` supports is a concept of \"local\" time. In particular, it","is limited to determining your system's default time zone offset, but nothing","more. That is, it doesn't support DST safe arithmetic:","","```rust","use anyhow::Context;","use time::{ext::NumericalDuration, macros::datetime, Duration};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // We create a fixed datetime for testing purposes,","    // but it's the same sort of value we would get back","    // from `OffsetDateTime::now_local()`.","    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);","    let dt2 = dt1.checked_add(1.hours())","      .context(\"datetime arithmetic failed\")?;","    // The 2 o'clock hour didn't exist on 2024-03-10","    // in New York.","    assert_eq!(dt2.to_string(), \"2024-03-10 2:30:00.0 -05:00:00\");","","    Ok(())","}","```","","`time`, in its present design, is fundamentally incapable of doing daylight","saving time safe arithmetic because its `OffsetDateTime` type doesn't know","anything about the time zone rules. Compare this with Jiff, which lets you not","only create a datetime with an offset, but with a _time zone_:","","```rust","use jiff::{civil::date, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2024, 3, 10).at(1, 30, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = zdt1.checked_add(1.hour())?;","    assert_eq!(zdt2.to_string(), \"2024-03-10T03:30:00-04:00[America/New_York]\");","","    Ok(())","}","```","","If you use `time-tz`, then you can make the above example with `time` work:","","```rust","use anyhow::Context;","use time::{ext::NumericalDuration, macros::datetime, Duration};","use time_tz::{OffsetDateTimeExt, Tz};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let tz = time_tz::timezones::db::america::NEW_YORK;","","    // We create a fixed datetime for testing purposes,","    // but it's the same sort of value we would get back","    // from `OffsetDateTime::now_local()`.","    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);","    let dt2 = dt1.checked_add(1.hours())","      .context(\"datetime arithmetic failed\")?","      .to_timezone(tz);","    assert_eq!(dt2.to_string(), \"2024-03-10 3:30:00.0 -04:00:00\");","","    Ok(())","}","```","","But note that you have to be careful to call `.to_timezone()` before printing","the datetime. In particular, there is no time zone aware datetime type.","","In my comparison with Chrono I went through a lot of examples involving","time zones. I did this because Chrono supports DST safe arithmetic generally,","but with a lot of nuanced differences from what Jiff supports. Conversely,","`time` doesn't have a time zone aware datetime type. And the time zone support","provided by `time-tz` is extremely limited. So at this time, in this document,","we won't belabor the point.","","### `time` supports its own custom format description","","Some users may find this easier to use:","","```rust","use time::{macros::format_description, OffsetDateTime};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let format = format_description!(","        \"[year]-[month]-[day] [hour]:[minute]:[second] \\","         [offset_hour sign:mandatory]:[offset_minute]:[offset_second]\"","    );","    let odt = OffsetDateTime::parse(\"2024-07-11 22:49:00 -04:00:00\", \u0026format)?;","    assert_eq!(odt.to_string(), \"2024-07-11 22:49:00.0 -04:00:00\");","","    Ok(())","}","```","","Jiff does support a `strptime`/`strftime` style API via the","`jiff::fmt::strtime` module:","","```rust","use jiff::Zoned;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt = Zoned::strptime(","      \"%Y-%m-%d %H:%M:%S %:z\",","      \"2024-07-11 22:49:00 -04:00:00\",","    )?;","    assert_eq!(zdt.to_string(), \"2024-07-11T22:49:00-04:00[-04:00]\");","","    Ok(())","}","```","","`time` also supports `strptime`/`strftime` style APIs:","","```rust","use time::OffsetDateTime;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // I don't believe `time` supports `%:z`, so we just drop the colons here.","    let format = time::format_description::parse_strftime_borrowed(","        \"%Y-%m-%d %H:%M:%S %z\"","    )?;","    let odt = OffsetDateTime::parse(\"2024-07-11 22:49:00 -0400\", \u0026format)?;","    assert_eq!(odt.to_string(), \"2024-07-11 22:49:00.0 -04:00:00\");","","    Ok(())","}","```","","### Jiff supports rounding datetimes","","We use a `Zoned` with a `TimeZone` that has a fixed offset. This is same as","`time`'s `OffsetDateTime` type:","","```rust","use jiff::{civil::date, tz::{self, TimeZone}, Unit, Zoned};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let tz = TimeZone::fixed(tz::offset(-4));","    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).to_zoned(tz)?;","    let zdt2 = zdt1.round(Unit::Hour)?;","    assert_eq!(zdt2.to_string(), \"2024-07-11T17:00:00-04:00[-04:00]\");","","    Ok(())","}","```","","Note though that because Jiff has support for time zones, you generally","shouldn't need to (and shouldn't _want_ to) use fixed offset datetimes. It's","because they don't take time zone rules into account and thus do not provide","DST safe arithmetic. Instead, the code above should be written like this","(unless you have a very specific reason to do otherwise):","","```rust","use jiff::{civil::date, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // Can also use `.to_zoned(TimeZone::system())` to use your system's","    // default time zone.","    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = zdt1.round(Unit::Hour)?;","    assert_eq!(zdt2.to_string(), \"2024-07-11T17:00:00-04:00[America/New_York]\");","","    Ok(())","}","```","","From here on, we won't use fixed offset datetimes in order to avoid encouraging","their use.","","The `time` crate has no rounding APIs.","","### Jiff supports rounding durations","","In Jiff, one can round the duration computed between two datetimes","","```rust","use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(\"America/New_York\")?;","","    let round_options = ZonedDifference::new(\u0026zdt2)","        .largest(Unit::Year)","        .smallest(Unit::Day)","        .mode(RoundMode::HalfExpand);","    let span = zdt1.until(round_options)?;","    assert_eq!(span, 22.years().months(7).days(24).fieldwise());","","    Ok(())","}","```","","The `time` crate has no rounding APIs.","","### Jiff provides support for calendar arithmetic","","With Jiff, you can add durations with calendar units:","","```rust","use jiff::{civil::date, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let zdt1 = date(2024, 7, 11).at(21, 0, 0, 0).in_tz(\"America/New_York\")?;","    let zdt2 = zdt1.checked_add(2.years().months(6).days(1))?;","    assert_eq!(zdt2.to_string(), \"2027-01-12T21:00:00-05:00[America/New_York]\");","","    Ok(())","}","```","","The `time` crate does provide a way to construct a `Duration` from units of","days via `Duration::days`, but this of course requires assuming that all days","are 24 hours long. And `time` does not support adding years or months.","","### Jiff supports conveniently re-balancing durations","","Aside from calendar arithmetic, Jiff also supports re-balancing durations","based on what you want the largest unit to be:","","```rust","use jiff::{SpanRound, ToSpan, Unit};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    // Balance down to seconds.","    let span1 = 4.hours().minutes(36).seconds(59);","    let span2 = span1.round(SpanRound::new().largest(Unit::Second))?;","    assert_eq!(span2, 16_619.seconds().fieldwise());","","    // Now go back by balancing up to hours.","    let span1 = 16_619.seconds();","    let span2 = span1.round(SpanRound::new().largest(Unit::Hour))?;","    assert_eq!(span2, 4.hours().minutes(36).seconds(59).fieldwise());","","    Ok(())","}","```","","The `time` crate's `Duration` type can go from bigger units down to smaller","units easily enough:","","```rust","use time::{ext::NumericalDuration, Duration};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let span = 4.hours() + 36.minutes() + 59.seconds();","    assert_eq!(span.whole_seconds(), 16_619);","    Ok(())","}","```","","But going from smaller units back up to larger units is difficult:","","```rust","use time::{ext::NumericalDuration, Duration};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let span = 16_619.seconds();","    assert_eq!(span.whole_hours(), 4);","    assert_eq!(span.whole_minutes(), 276);","    assert_eq!(span.whole_seconds(), 16_619);","","    Ok(())","}","```","","Notice that the accessors just report how many whole units the span is. You","can't get the span broken down into smaller units. To achieve that, you need to","do the arithmetic yourself:","","```rust","use time::{convert::{Hour, Minute, Second}, ext::NumericalDuration, Duration};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let mut span = 16_619.seconds();","    assert_eq!(span.whole_hours(), 4);","    assert_eq!(span.whole_minutes() % Minute::per(Hour) as i64, 36);","    assert_eq!(span.whole_seconds() % Second::per(Minute) as i64, 59);","","    Ok(())","}","```","","### Jiff is generally faster than `time`","","When it comes to parsing and printing, Jiff is generally faster than `time`","although not always. `time` is sometimes faster than Jiff on date arithmetic,","but not by much. (Some of these may be due to faster equality comparisons on","date values, on which `time` is legitimately faster at than Jiff at present.)","","The following results were collected with `time 0.3.47`.","","```text","$ cd bench","$ cargo bench -- --save-baseline baseline","[.. snip ..]","$ critcmp base -g '(.*)/(?:jiff|time)$'","group                                                           baseline//time                       baseline//jiff","-----                                                           --------------                       --------------","civil_datetime/add_days/diffyear/duration                       1.00      7.8±0.08ns        ? ?/sec  1.67     12.9±0.19ns        ? ?/sec","civil_datetime/add_days/diffyear/span                                                                1.00     18.0±0.28ns        ? ?/sec","civil_datetime/add_days/sameyear/duration                       1.00      7.8±0.11ns        ? ?/sec  1.66     12.9±0.16ns        ? ?/sec","civil_datetime/add_days/sameyear/span                                                                1.00     18.0±0.25ns        ? ?/sec","date/add_days/diffyear/duration                                 1.00      3.8±0.02ns        ? ?/sec  1.67      6.3±0.04ns        ? ?/sec","date/add_days/diffyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec","date/add_days/one/duration                                      1.00      3.8±0.03ns        ? ?/sec  1.38      5.2±0.03ns        ? ?/sec","date/add_days/one/span                                                                               1.00      5.8±0.06ns        ? ?/sec","date/add_days/sameyear/duration                                 1.00      3.8±0.04ns        ? ?/sec  1.68      6.4±0.07ns        ? ?/sec","date/add_days/sameyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec","date/days_in_month/leap/feb                                     1.90      1.1±0.01ns        ? ?/sec  1.00      0.6±0.03ns        ? ?/sec","date/days_in_month/leap/nofeb                                   2.70      1.0±0.01ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec","date/days_in_month/noleap/feb                                   2.78      1.1±0.02ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec","date/days_in_month/noleap/nofeb                                 2.70      1.0±0.02ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec","date/difference_days/duration                                   1.00      2.1±0.02ns        ? ?/sec  1.41      2.9±0.04ns        ? ?/sec","date/difference_days/span                                                                            1.00      2.4±0.03ns        ? ?/sec","date/tomorrow/diff-month                                        1.00      0.4±0.02ns        ? ?/sec  3.42      1.4±0.01ns        ? ?/sec","date/tomorrow/diff-year                                         1.00      1.0±0.01ns        ? ?/sec  1.59      1.5±0.01ns        ? ?/sec","date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec  2.25      0.9±0.01ns        ? ?/sec","date/yesterday/diff-month                                       1.00      0.4±0.01ns        ? ?/sec  3.65      1.4±0.02ns        ? ?/sec","date/yesterday/diff-year                                        1.00      0.9±0.01ns        ? ?/sec  1.35      1.2±0.02ns        ? ?/sec","date/yesterday/same-month                                       1.00      0.4±0.02ns        ? ?/sec  2.06      0.8±0.01ns        ? ?/sec","datetime/add_years_months_days                                                                       1.00     29.1±0.18ns        ? ?/sec","parse/civil_datetime                                            1.00     12.9±0.19ns        ? ?/sec  1.63     21.1±0.19ns        ? ?/sec","parse/rfc2822                                                   2.24     43.4±1.90ns        ? ?/sec  1.00     19.4±0.15ns        ? ?/sec","parse/strptime/oneshot                                                                               1.00     62.2±0.39ns        ? ?/sec","parse/strptime/prebuilt                                         1.00     73.7±0.91ns        ? ?/sec","print/civil_datetime                                            3.27     37.4±0.32ns        ? ?/sec  1.00     11.4±0.04ns        ? ?/sec","print/rfc2822/buffer                                            1.55     20.4±0.08ns        ? ?/sec  1.00     13.2±0.05ns        ? ?/sec","print/rfc2822/to_string                                         3.61     72.0±1.25ns        ? ?/sec  1.00     19.9±0.06ns        ? ?/sec","print/rfc3339/buffer                                            1.33     22.1±0.29ns        ? ?/sec  1.00     16.7±0.11ns        ? ?/sec","print/rfc3339/to_string                                         2.91     68.1±1.30ns        ? ?/sec  1.00     23.4±0.12ns        ? ?/sec","print/rfc9557/buffer                                                                                 1.00     16.2±0.07ns        ? ?/sec","print/rfc9557/to_string                                                                              1.00     22.6±0.20ns        ? ?/sec","print/strftime/oneshot/buffer                                   6.88    421.5±1.39ns        ? ?/sec  1.00     61.3±0.82ns        ? ?/sec","print/strftime/oneshot/to_string                                5.59    434.0±1.44ns        ? ?/sec  1.00     77.7±0.96ns        ? ?/sec","print/strftime/oneshot/zoned                                                                         1.00     74.6±1.07ns        ? ?/sec","print/strftime/prebuilt/buffer                                  1.00     97.7±0.99ns        ? ?/sec","print/strftime/prebuilt/buffer/bespoke                          1.00    105.8±1.45ns        ? ?/sec","print/strftime/prebuilt/to_string                               1.00    165.3±1.19ns        ? ?/sec","print/strftime/prebuilt/to_string/bespoke                       1.00    175.0±1.79ns        ? ?/sec","timestamp/add_time_secs/duration                                3.82      9.6±0.04ns        ? ?/sec  1.00      2.5±0.03ns        ? ?/sec","timestamp/add_time_secs/span                                                                         1.00      3.7±0.05ns        ? ?/sec","timestamp/add_time_subsec/duration                              3.33      9.7±0.09ns        ? ?/sec  1.00      2.9±0.03ns        ? ?/sec","timestamp/add_time_subsec/span                                                                       1.00      7.8±0.08ns        ? ?/sec","timestamp/every_hour_in_week/byhand                             14.30 1530.8±16.96ns        ? ?/sec  1.00    107.1±0.74ns        ? ?/sec","timestamp/every_hour_in_week/series                                                                  1.00    105.8±1.01ns        ? ?/sec","timestamp/from_seconds/integer                                  11.69     4.4±0.03ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec","timestamp/to_civil_datetime_offset_conversion                   1.00      3.9±0.03ns        ? ?/sec  1.49      5.8±0.04ns        ? ?/sec","timestamp/to_civil_datetime_offset_holistic                     1.00      4.6±0.03ns        ? ?/sec  1.04      4.8±0.04ns        ? ?/sec","zoned/fixed_offset_add_time/duration                            1.00      9.6±0.09ns        ? ?/sec  1.06     10.3±0.08ns        ? ?/sec","zoned/fixed_offset_add_time/span                                                                     1.00     16.9±0.12ns        ? ?/sec","zoned/fixed_offset_to_civil_datetime                            1.00      0.6±0.00ns        ? ?/sec  7.32      4.2±0.01ns        ? ?/sec","zoned/fixed_offset_to_timestamp                                 6.08      1.8±0.02ns        ? ?/sec  1.00      0.3±0.01ns        ? ?/sec","```","","Questions about benchmarks are welcome in","[Discussions on GitHub](https://github.com/BurntSushi/jiff/discussions).","","## [`hifitime`](https://docs.rs/hifitime) (v3.9.0)","","`hifitime` is a datetime library with a focus on engineering and scientific","calculations where general relativity and time dilation matter. It supports","conversion between many different time scales: TAI, Terrestrial Time, UTC, GPST","and more. It also supports leap seconds.","","For the following comparisons, a `Cargo.toml` with the following dependencies","should be able to run any of the programs in this section:","","```toml","anyhow = \"1.0.81\"","hifitime = \"3.9.0\"","jiff = { version = \"0.2.0\", features = [\"serde\"] }","```","","### Time zone database integration","","Like the `time` crate, `hifitime` does not support time zones and does not have","any integration with the Time Zone Database. `hifitime` doesn't have any","equivalent to `OffsetDateTime` like in `time` either. The only datetime type","that `hifitime` has is `Epoch`, and it is an absolute time. While you can","convert between it and civil time (assuming civil time is in UTC), there is no","data type in `hifitime` for representing civil time.","","### `hifitime` supports leap seconds","","In particular, when computing a duration from two `Epoch` values that spans","a positive leap second (a second gets repeated), `hifitime` will correctly","report the accurate duration. With that said, to get an accurate duration, one","of the two time scales has to be converted to to TAI (or another time scale","which does not have leap seconds):","","```rust","use hifitime::{Duration, Epoch, TimeScale};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let e1: Epoch = \"2015-06-30T23:00:00 UTC\".parse()?;","    let e2: Epoch = \"2015-07-01T00:00:00 UTC\".parse()?;","    let e2 = e2.to_time_scale(TimeScale::TAI);","","    let duration = e2 - e1;","    assert_eq!(duration, Duration::from_seconds(3_601.0));","","    Ok(())","}","```","","Jiff, however, [does not support leap seconds][jiff-leap-seconds]:","","```rust","use jiff::{Timestamp, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let ts1: Timestamp = \"2015-06-30T23:00:00Z\".parse()?;","    let ts2: Timestamp = \"2015-07-01T00:00:00Z\".parse()?;","    let span = ts2 - ts1;","    assert_eq!(span, 3_600.seconds().fieldwise());","","    Ok(())","}","```","","So in this case, Jiff reports `3,600` seconds as the duration, but the _actual_","duration was `3,601` seconds, as reported by `hifitime`.","","[jiff-leap-seconds]: https://github.com/BurntSushi/jiff/issues/7","","### Jiff makes checked or saturating arithmetic explicit","","For Jiff, whether you want to saturate or not is an explicit part of the API.","And implementations of the `Add` operator will panic on overflow:","","```rust","use jiff::{Timestamp, ToSpan};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let ts = Timestamp::MAX;","    assert!(ts.checked_add(1.day()).is_err());","    assert_eq!(ts.saturating_add(1.hour())?, ts);","","    Ok(())","}","```","","In contrast, `hifitime` appears to use saturating arithmetic everywhere (I've","not been able to find this behavior documented though, so I'm not clear on what","the intended semantics are):","","```rust","use hifitime::{Duration, Epoch};","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let e1 = Epoch::from_unix_seconds(f64::MAX);","    let e2 = e1 + Duration::from_days(1.0);","    assert_eq!(e1, e2);","","    Ok(())","}","```","","","## [`icu`](https://docs.rs/icu) (v1.5.0)","","The ICU4X project fulfils a slightly different need than `jiff`. Its main","features are calendrical calculations (`icu::calendar`), supporting conversions","between different calendar systems such as Gregorian, Buddhist, Islamic,","Japanese, etc., as well as localized datetime formatting (`icu::datetime`).","","It does not perform datetime or time-zone arithmetic, and does not have a","timestamp or duration type.","","`icu` can be used to complement `jiff` when localized date formatting or","calendar conversions are required. To facilitate this, the","[`jiff-icu`](https://docs.rs/jiff-icu) crate makes conversions between Jiff","and ICU4X data types seamless. For example, to do localization starting from","a Jiff data type:","","```text","use icu::{","    calendar::{japanese::Japanese, DateTime},","    datetime::TypedDateTimeFormatter,","    locid::locale,","};","use jiff::Timestamp;","use jiff_icu::ConvertFrom as _;","","fn main() -\u003e anyhow::Result\u003c()\u003e {","    let ts: Timestamp = \"2024-09-10T23:37:20Z\".parse()?;","    let zoned = ts.in_tz(\"Asia/Tokyo\")?;","","    // Create ICU datetime.","    let datetime = DateTime::convert_from(zoned.datetime());","","    // Convert to Japanese calendar.","    let japanese_datetime = DateTime::new_from_iso(datetime, Japanese::new());","","    // Format for the en-GB locale.","    let formatter = TypedDateTimeFormatter::try_new(","        \u0026locale!(\"en-GB\").into(),","        Default::default(),","    )?;","","    // Assert that we get the expected result.","    assert_eq!(","        formatter.format(\u0026japanese_datetime).to_string(),","        \"Sept 11, 6 Reiwa, 08:37:20\",","    );","","    Ok(())","}","```","","The above example requires the following dependency specifications:","","```toml","anyhow = \"1.0.81\"","icu = { version = \"1.5.0\", features = [\"std\"] }","jiff = { version = \"0.1.0\", features = [\"serde\"] }","jiff-icu = { version = \"0.1.0\" }","```"],"stylingDirectives":[[[0,44,"pl-mh"],[2,44,"pl-en"]],[],[],[],[],[],[],[],[[38,39,"pl-s"],[50,51,"pl-s"],[56,57,"pl-s"]],[[8,9,"pl-s"]],[],[[61,62,"pl-s"],[62,66,"pl-c1"],[66,67,"pl-s"]],[[66,67,"pl-s"],[74,75,"pl-s"]],[],[],[],[],[],[],[[9,10,"pl-s"],[21,22,"pl-s"]],[],[],[],[],[[55,56,"pl-s"],[66,67,"pl-s"]],[[0,1,"pl-s"],[7,8,"pl-s"]],[],[],[],[],[[0,1,"pl-s"],[1,44,"pl-c1"],[44,45,"pl-s"]],[],[[0,47,"pl-mh"],[3,47,"pl-en"],[3,4,"pl-s"],[4,5,"pl-s"],[5,11,"pl-c1"],[11,12,"pl-s"],[12,13,"pl-s"],[13,14,"pl-s"],[14,36,"pl-corl"],[36,37,"pl-s"]],[],[],[],[],[[33,34,"pl-s"],[34,44,"pl-c1"],[44,45,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-smi"],[9,17,"pl-s"],[9,10,"pl-pds"],[16,17,"pl-pds"]],[[0,6,"pl-smi"],[9,17,"pl-s"],[9,10,"pl-pds"],[16,17,"pl-pds"]],[[0,9,"pl-smi"],[14,21,"pl-smi"],[24,31,"pl-s"],[24,25,"pl-pds"],[30,31,"pl-pds"],[33,41,"pl-smi"],[45,52,"pl-s"],[45,46,"pl-pds"],[51,52,"pl-pds"]],[[0,4,"pl-smi"],[9,16,"pl-smi"],[19,26,"pl-s"],[19,20,"pl-pds"],[25,26,"pl-pds"],[28,36,"pl-smi"],[40,47,"pl-s"],[40,41,"pl-pds"],[46,47,"pl-pds"]],[[0,5,"pl-smi"],[8,17,"pl-s"],[8,9,"pl-pds"],[16,17,"pl-pds"]],[[0,10,"pl-smi"],[13,22,"pl-s"],[13,14,"pl-pds"],[21,22,"pl-pds"]],[[0,6,"pl-smi"],[9,16,"pl-s"],[9,10,"pl-pds"],[15,16,"pl-pds"]],[[0,3,"pl-s"]],[],[[0,34,"pl-mh"],[4,34,"pl-en"]],[],[],[[31,32,"pl-s"],[32,51,"pl-c1"],[51,52,"pl-s"]],[[46,47,"pl-s"],[47,56,"pl-c1"],[56,57,"pl-s"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[10,15,"pl-en"],[15,17,"pl-k"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,18,"pl-en"],[19,23,"pl-c1"],[25,26,"pl-c1"],[28,30,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-en"],[35,36,"pl-c1"],[38,40,"pl-c1"],[42,43,"pl-c1"],[45,46,"pl-c1"],[47,48,"pl-k"],[48,53,"pl-en"],[54,72,"pl-s"],[54,55,"pl-pds"],[71,72,"pl-pds"],[73,74,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,77,"pl-s"],[32,33,"pl-pds"],[76,77,"pl-pds"]],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[0,1,"pl-s"],[1,2,"pl-s"],[2,11,"pl-c1"],[11,12,"pl-s"],[12,13,"pl-s"],[13,14,"pl-s"],[14,39,"pl-corl"],[39,40,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,20,"pl-en"]],[[0,3,"pl-k"],[4,13,"pl-en"],[13,15,"pl-k"],[15,22,"pl-en"],[22,24,"pl-k"],[24,32,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,22,"pl-en"],[22,23,"pl-k"],[23,39,"pl-en"],[40,44,"pl-c1"],[46,47,"pl-c1"],[49,51,"pl-c1"],[53,54,"pl-c1"],[56,58,"pl-c1"],[60,61,"pl-c1"]],[[8,9,"pl-k"],[9,15,"pl-en"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,37,"pl-s"],[17,18,"pl-pds"],[36,37,"pl-pds"],[38,39,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,57,"pl-s"],[32,33,"pl-pds"],[56,57,"pl-pds"]],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,10,"pl-c1"],[10,11,"pl-s"]],[],[[13,14,"pl-s"],[14,17,"pl-c1"],[17,18,"pl-s"]],[[0,1,"pl-s"],[1,10,"pl-c1"],[10,11,"pl-s"]],[],[[47,48,"pl-s"],[48,56,"pl-c1"],[56,57,"pl-s"]],[[6,7,"pl-s"],[7,11,"pl-c1"],[11,12,"pl-s"],[19,20,"pl-s"],[20,23,"pl-c1"],[23,24,"pl-s"],[52,53,"pl-s"],[53,69,"pl-c1"],[69,70,"pl-s"]],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"],[32,33,"pl-s"],[33,41,"pl-c1"],[41,42,"pl-s"],[52,53,"pl-s"],[53,57,"pl-c1"],[57,58,"pl-s"],[68,69,"pl-s"],[69,74,"pl-c1"],[74,75,"pl-s"]],[[9,10,"pl-s"],[10,18,"pl-c1"],[18,19,"pl-s"],[23,24,"pl-s"],[24,29,"pl-c1"],[29,30,"pl-s"],[40,41,"pl-s"],[41,45,"pl-c1"],[45,46,"pl-s"]],[],[[34,35,"pl-s"],[35,36,"pl-s"],[36,42,"pl-c1"],[42,43,"pl-s"],[43,44,"pl-s"],[44,45,"pl-s"],[45,67,"pl-corl"],[67,68,"pl-s"]],[[7,8,"pl-s"],[8,17,"pl-c1"],[17,18,"pl-s"],[24,25,"pl-s"],[25,31,"pl-c1"],[31,32,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,20,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,14,"pl-en"]],[],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,15,"pl-en"],[15,17,"pl-k"],[17,22,"pl-en"],[23,41,"pl-s"],[23,24,"pl-pds"],[40,41,"pl-pds"],[42,43,"pl-k"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[15,16,"pl-k"],[16,18,"pl-smi"],[19,20,"pl-k"],[20,36,"pl-en"],[37,41,"pl-c1"],[43,44,"pl-c1"],[46,48,"pl-c1"],[50,51,"pl-c1"],[53,55,"pl-c1"],[57,58,"pl-c1"]],[[8,9,"pl-k"],[9,15,"pl-en"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,37,"pl-s"],[17,18,"pl-pds"],[36,37,"pl-pds"],[38,39,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,57,"pl-s"],[32,33,"pl-pds"],[56,57,"pl-pds"]],[[4,6,"pl-en"]],[],[],[[0,56,"pl-c"],[0,2,"pl-c"]],[[0,60,"pl-c"],[0,2,"pl-c"]],[[0,14,"pl-c"],[0,2,"pl-c"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[50,51,"pl-s"],[51,68,"pl-c1"],[68,69,"pl-s"]],[],[],[],[],[[0,56,"pl-mh"],[4,56,"pl-en"]],[],[[14,15,"pl-s"],[15,20,"pl-c1"],[20,21,"pl-s"]],[[0,1,"pl-s"],[1,6,"pl-c1"],[6,7,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,30,"pl-en"],[32,37,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,18,"pl-en"],[19,23,"pl-c1"],[25,26,"pl-c1"],[28,30,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-en"],[35,36,"pl-c1"],[38,40,"pl-c1"],[42,44,"pl-c1"],[46,47,"pl-c1"],[48,49,"pl-k"],[49,54,"pl-en"],[55,73,"pl-s"],[55,56,"pl-pds"],[72,73,"pl-pds"],[74,75,"pl-k"]],[],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,25,"pl-en"],[25,27,"pl-k"],[27,43,"pl-en"],[44,45,"pl-k"],[45,48,"pl-smi"],[49,50,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,70,"pl-s"],[21,22,"pl-pds"],[22,24,"pl-cce"],[22,23,"pl-cce"],[67,69,"pl-cce"],[67,68,"pl-cce"],[69,70,"pl-pds"]],[],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,18,"pl-en"],[19,20,"pl-k"],[21,31,"pl-en"],[31,33,"pl-k"],[33,41,"pl-en"],[42,43,"pl-k"],[43,47,"pl-smi"],[48,49,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,77,"pl-s"],[32,33,"pl-pds"],[76,77,"pl-pds"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,30,"pl-en"],[31,32,"pl-c1"],[32,33,"pl-k"],[33,39,"pl-en"],[42,43,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,78,"pl-s"],[33,34,"pl-pds"],[77,78,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[46,47,"pl-s"],[47,52,"pl-c1"],[52,53,"pl-s"]],[],[[19,20,"pl-s"],[20,23,"pl-c1"],[23,24,"pl-s"],[28,29,"pl-s"],[29,32,"pl-c1"],[32,33,"pl-s"]],[],[[45,46,"pl-s"],[46,51,"pl-c1"],[51,52,"pl-s"],[67,68,"pl-s"],[68,77,"pl-c1"],[77,78,"pl-s"]],[[3,4,"pl-s"],[4,10,"pl-c1"],[10,11,"pl-s"],[38,39,"pl-s"],[39,44,"pl-c1"],[44,45,"pl-s"],[68,69,"pl-s"],[69,77,"pl-c1"],[77,78,"pl-s"]],[],[],[[0,3,"pl-s"],[3,14,"pl-en"],[14,14,"pl-c1"]],[[0,20,"pl-c1"]],[[0,64,"pl-c1"]],[[0,0,"pl-c1"]],[[0,33,"pl-c1"]],[[0,60,"pl-c1"]],[[0,17,"pl-c1"]],[[0,40,"pl-c1"]],[[0,0,"pl-c1"]],[[0,51,"pl-c1"]],[[0,62,"pl-c1"]],[[0,61,"pl-c1"]],[[0,19,"pl-c1"]],[[0,54,"pl-c1"]],[[0,0,"pl-c1"]],[[0,60,"pl-c1"]],[[0,61,"pl-c1"]],[[0,65,"pl-c1"]],[[0,66,"pl-c1"]],[[0,62,"pl-c1"]],[[0,60,"pl-c1"]],[[0,39,"pl-c1"]],[[0,59,"pl-c1"]],[[0,17,"pl-c1"]],[[0,63,"pl-c1"]],[[0,0,"pl-c1"]],[[0,62,"pl-c1"]],[[0,66,"pl-c1"]],[[0,64,"pl-c1"]],[[0,60,"pl-c1"]],[[0,62,"pl-c1"]],[[0,60,"pl-c1"]],[[0,39,"pl-c1"]],[[0,63,"pl-c1"]],[[0,0,"pl-c1"]],[[0,10,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[18,19,"pl-s"],[19,21,"pl-c1"],[21,22,"pl-s"],[28,29,"pl-s"],[29,38,"pl-c1"],[38,39,"pl-s"],[65,66,"pl-s"],[66,75,"pl-c1"],[75,76,"pl-s"]],[[48,49,"pl-s"],[49,70,"pl-c1"],[70,71,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[13,21,"pl-en"],[23,34,"pl-en"],[36,45,"pl-en"],[47,55,"pl-en"]],[[0,3,"pl-k"],[4,13,"pl-en"],[13,15,"pl-k"],[15,22,"pl-en"],[22,24,"pl-k"],[24,32,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,22,"pl-en"],[22,23,"pl-k"],[23,39,"pl-en"],[40,44,"pl-c1"],[46,47,"pl-c1"],[49,51,"pl-c1"],[53,54,"pl-c1"],[56,58,"pl-c1"],[60,62,"pl-c1"]],[[8,9,"pl-k"],[9,15,"pl-en"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,37,"pl-s"],[17,18,"pl-pds"],[36,37,"pl-pds"],[38,39,"pl-k"]],[],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,25,"pl-en"],[25,27,"pl-k"],[27,43,"pl-en"],[44,45,"pl-k"],[45,48,"pl-smi"],[48,49,"pl-k"],[49,61,"pl-en"],[64,65,"pl-k"]],[[4,62,"pl-c"],[4,6,"pl-c"]],[[4,61,"pl-c"],[4,6,"pl-c"]],[[4,19,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,52,"pl-s"],[21,22,"pl-pds"],[22,24,"pl-cce"],[22,23,"pl-cce"],[49,51,"pl-cce"],[49,50,"pl-cce"],[51,52,"pl-pds"]],[],[[4,60,"pl-c"],[4,6,"pl-c"]],[[4,61,"pl-c"],[4,6,"pl-c"]],[[4,65,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,21,"pl-en"],[22,33,"pl-en"],[35,36,"pl-k"],[37,47,"pl-en"],[47,49,"pl-k"],[49,57,"pl-en"],[58,59,"pl-k"],[59,63,"pl-smi"],[64,65,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,60,"pl-s"],[32,33,"pl-pds"],[59,60,"pl-pds"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,37,"pl-en"],[38,47,"pl-en"],[47,49,"pl-k"],[49,56,"pl-en"],[57,58,"pl-c1"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,36,"pl-s"],[17,18,"pl-pds"],[35,36,"pl-pds"],[37,38,"pl-k"]],[[4,59,"pl-c"],[4,6,"pl-c"]],[[4,17,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,61,"pl-s"],[33,34,"pl-pds"],[60,61,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[47,48,"pl-s"],[48,57,"pl-c1"],[57,58,"pl-s"]],[[28,29,"pl-s"],[37,38,"pl-s"]],[],[[59,60,"pl-s"],[63,64,"pl-s"]],[],[],[],[],[[0,1,"pl-s"],[1,9,"pl-en"],[9,10,"pl-s"],[12,53,"pl-corl"]],[],[[0,60,"pl-mh"],[4,60,"pl-en"]],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,30,"pl-en"],[32,36,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,30,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-en"],[35,37,"pl-c1"],[39,40,"pl-c1"],[42,43,"pl-c1"],[45,46,"pl-c1"],[47,48,"pl-k"],[48,53,"pl-en"],[54,72,"pl-s"],[54,55,"pl-pds"],[71,72,"pl-pds"],[73,74,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,31,"pl-en"],[32,33,"pl-c1"],[33,34,"pl-k"],[34,37,"pl-en"],[40,41,"pl-k"]],[],[[4,69,"pl-c"],[4,6,"pl-c"]],[[4,48,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,78,"pl-s"],[33,34,"pl-pds"],[77,78,"pl-pds"]],[[4,36,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,16,"pl-k"],[16,20,"pl-smi"],[21,22,"pl-k"],[23,24,"pl-k"],[24,28,"pl-smi"],[30,32,"pl-c1"],[32,33,"pl-k"],[33,38,"pl-en"],[40,41,"pl-k"],[41,50,"pl-en"]],[[4,71,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[27,31,"pl-en"],[31,33,"pl-k"],[33,36,"pl-en"],[38,39,"pl-k"],[39,43,"pl-smi"],[45,46,"pl-k"],[48,49,"pl-c1"],[49,50,"pl-k"],[50,53,"pl-en"],[55,56,"pl-k"],[56,65,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[],[],[],[],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[13,17,"pl-en"],[19,28,"pl-en"],[30,38,"pl-en"]],[[0,3,"pl-k"],[4,13,"pl-en"],[13,15,"pl-k"],[15,22,"pl-en"],[22,24,"pl-k"],[24,32,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,23,"pl-en"],[23,24,"pl-k"],[24,40,"pl-en"],[41,45,"pl-c1"],[47,48,"pl-c1"],[50,51,"pl-c1"],[53,55,"pl-c1"],[57,58,"pl-c1"],[60,61,"pl-c1"]],[[8,9,"pl-k"],[9,15,"pl-en"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,37,"pl-s"],[17,18,"pl-pds"],[36,37,"pl-pds"],[38,39,"pl-k"]],[],[[4,59,"pl-c"],[4,6,"pl-c"]],[[4,62,"pl-c"],[4,6,"pl-c"]],[[4,60,"pl-c"],[4,6,"pl-c"]],[[4,36,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,38,"pl-en"],[39,48,"pl-en"],[48,50,"pl-k"],[50,54,"pl-en"],[55,56,"pl-c1"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,45,"pl-s"],[17,18,"pl-pds"],[44,45,"pl-pds"],[46,47,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,58,"pl-s"],[33,34,"pl-pds"],[57,58,"pl-pds"]],[],[[4,60,"pl-c"],[4,6,"pl-c"]],[[4,56,"pl-c"],[4,6,"pl-c"]],[[4,22,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,36,"pl-en"],[37,41,"pl-en"],[41,43,"pl-k"],[43,46,"pl-en"],[47,48,"pl-c1"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,37,"pl-s"],[17,18,"pl-pds"],[36,37,"pl-pds"],[38,39,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,58,"pl-s"],[33,34,"pl-pds"],[57,58,"pl-pds"]],[],[[4,63,"pl-c"],[4,6,"pl-c"]],[[4,39,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,20,"pl-smi"],[20,21,"pl-k"],[21,42,"pl-en"],[43,44,"pl-k"],[44,48,"pl-smi"]],[[4,60,"pl-c"],[4,6,"pl-c"]],[[4,61,"pl-c"],[4,6,"pl-c"]],[[4,62,"pl-c"],[4,6,"pl-c"]],[[4,43,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[20,21,"pl-k"],[21,29,"pl-en"],[33,34,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,40,"pl-mh"],[4,40,"pl-en"]],[],[],[[27,28,"pl-s"],[28,32,"pl-c1"],[32,33,"pl-s"],[42,43,"pl-s"],[43,47,"pl-c1"],[47,48,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,15,"pl-en"],[17,23,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,16,"pl-c1"],[16,17,"pl-k"],[17,22,"pl-en"],[24,25,"pl-k"],[25,31,"pl-en"],[32,33,"pl-c1"],[34,35,"pl-k"],[35,39,"pl-en"],[40,41,"pl-c1"],[42,43,"pl-k"],[43,48,"pl-en"],[49,51,"pl-c1"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,25,"pl-en"],[25,27,"pl-k"],[27,43,"pl-en"],[44,45,"pl-k"],[45,49,"pl-smi"],[50,51,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,38,"pl-s"],[21,22,"pl-pds"],[22,24,"pl-cce"],[22,23,"pl-cce"],[35,37,"pl-cce"],[35,36,"pl-cce"],[37,38,"pl-pds"]],[],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,17,"pl-en"],[18,19,"pl-k"],[20,30,"pl-en"],[30,32,"pl-k"],[32,40,"pl-en"],[41,42,"pl-k"],[42,46,"pl-smi"],[47,48,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[20,24,"pl-smi"],[24,25,"pl-k"],[25,34,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[7,8,"pl-s"],[67,68,"pl-s"],[68,69,"pl-s"],[69,83,"pl-en"],[83,84,"pl-s"]],[],[[0,1,"pl-s"],[1,15,"pl-en"],[15,16,"pl-s"],[18,65,"pl-corl"]],[],[[0,49,"pl-mh"],[4,49,"pl-en"]],[],[],[],[],[],[],[],[],[[47,48,"pl-s"],[56,57,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[10,15,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,72,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,18,"pl-en"],[19,20,"pl-k"],[21,57,"pl-s"],[21,22,"pl-pds"],[56,57,"pl-pds"],[57,58,"pl-k"],[58,63,"pl-en"],[65,66,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,77,"pl-s"],[32,33,"pl-pds"],[76,77,"pl-pds"]],[],[[4,75,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,18,"pl-en"],[19,20,"pl-k"],[21,57,"pl-s"],[21,22,"pl-pds"],[56,57,"pl-pds"],[57,58,"pl-k"],[58,63,"pl-en"],[65,66,"pl-k"]],[[4,50,"pl-c"],[4,6,"pl-c"]],[[4,38,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,77,"pl-s"],[32,33,"pl-pds"],[76,77,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[14,15,"pl-s"],[15,33,"pl-c1"],[33,34,"pl-s"],[36,37,"pl-s"],[37,59,"pl-c1"],[59,60,"pl-s"]],[[0,1,"pl-s"],[1,20,"pl-c1"],[20,21,"pl-s"]],[],[],[[54,55,"pl-s"],[55,76,"pl-c1"],[76,77,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,36,"pl-en"],[38,46,"pl-en"]],[[0,3,"pl-k"],[4,13,"pl-en"],[13,15,"pl-k"],[15,22,"pl-en"],[22,24,"pl-k"],[24,32,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,58,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,14,"pl-smi"],[15,16,"pl-k"],[17,25,"pl-en"],[25,26,"pl-k"],[26,42,"pl-en"],[43,47,"pl-c1"],[49,50,"pl-c1"],[52,54,"pl-c1"],[56,57,"pl-c1"],[59,61,"pl-c1"],[63,64,"pl-c1"]],[[4,14,"pl-en"],[15,21,"pl-smi"],[23,38,"pl-en"],[38,40,"pl-k"],[40,44,"pl-en"]],[],[[4,51,"pl-c"],[4,6,"pl-c"]],[[4,60,"pl-c"],[4,6,"pl-c"]],[[4,29,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,22,"pl-en"],[22,23,"pl-k"],[23,39,"pl-en"],[40,44,"pl-c1"],[46,48,"pl-c1"],[50,51,"pl-c1"],[53,54,"pl-c1"],[56,58,"pl-c1"],[60,61,"pl-c1"]],[[8,9,"pl-k"],[9,17,"pl-en"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,35,"pl-s"],[17,18,"pl-pds"],[34,35,"pl-pds"],[36,37,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,57,"pl-s"],[32,33,"pl-pds"],[56,57,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,9,"pl-en"],[9,10,"pl-s"],[12,57,"pl-corl"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,33,"pl-en"],[35,41,"pl-en"],[43,47,"pl-en"],[49,64,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,28,"pl-c1"],[30,32,"pl-c1"],[33,34,"pl-k"],[34,36,"pl-en"],[37,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[],[[4,7,"pl-k"],[8,21,"pl-smi"],[22,23,"pl-k"],[24,39,"pl-en"],[39,41,"pl-k"],[41,44,"pl-en"],[45,46,"pl-k"],[46,50,"pl-smi"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,21,"pl-en"],[21,23,"pl-k"],[23,27,"pl-en"]],[[8,9,"pl-k"],[9,17,"pl-en"],[18,22,"pl-en"],[22,24,"pl-k"],[24,27,"pl-en"]],[[8,9,"pl-k"],[9,13,"pl-en"],[14,23,"pl-en"],[23,25,"pl-k"],[25,35,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[26,39,"pl-smi"],[40,41,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,35,"pl-c1"],[35,36,"pl-k"],[36,41,"pl-en"],[43,44,"pl-k"],[44,50,"pl-en"],[51,52,"pl-c1"],[53,54,"pl-k"],[54,58,"pl-en"],[59,61,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[0,1,"pl-s"],[1,32,"pl-c1"],[32,33,"pl-s"]],[[49,50,"pl-s"],[50,59,"pl-c1"],[59,60,"pl-s"]],[[14,15,"pl-s"],[15,34,"pl-c1"],[34,35,"pl-s"]],[],[],[],[],[[0,50,"pl-mh"],[4,50,"pl-en"]],[],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,33,"pl-en"],[35,41,"pl-en"],[43,47,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,14,"pl-smi"],[15,16,"pl-k"],[17,21,"pl-en"],[22,26,"pl-c1"],[28,29,"pl-c1"],[31,33,"pl-c1"],[34,35,"pl-k"],[35,40,"pl-en"],[41,59,"pl-s"],[41,42,"pl-pds"],[58,59,"pl-pds"],[60,61,"pl-k"]],[[4,7,"pl-k"],[8,15,"pl-smi"],[16,17,"pl-k"],[18,22,"pl-en"],[23,27,"pl-c1"],[29,31,"pl-c1"],[33,34,"pl-c1"],[35,36,"pl-k"],[36,41,"pl-en"],[42,60,"pl-s"],[42,43,"pl-pds"],[59,60,"pl-pds"],[61,62,"pl-k"]],[],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,18,"pl-c1"],[18,19,"pl-k"],[19,24,"pl-en"],[26,27,"pl-k"],[27,34,"pl-en"],[35,37,"pl-c1"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"]],[[8,17,"pl-en"],[17,19,"pl-k"],[19,22,"pl-en"],[24,25,"pl-k"],[25,33,"pl-en"],[34,38,"pl-en"],[38,40,"pl-k"],[40,43,"pl-en"],[44,45,"pl-k"],[45,53,"pl-en"],[54,55,"pl-k"],[55,61,"pl-smi"]],[[5,6,"pl-k"]],[[4,74,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,23,"pl-c1"],[23,24,"pl-k"],[24,27,"pl-en"],[29,30,"pl-k"],[30,39,"pl-en"]],[],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,18,"pl-c1"],[18,19,"pl-k"],[19,24,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"]],[[8,17,"pl-en"],[17,19,"pl-k"],[19,22,"pl-en"],[24,25,"pl-k"],[25,33,"pl-en"],[34,38,"pl-en"],[38,40,"pl-k"],[40,43,"pl-en"],[44,45,"pl-k"],[45,53,"pl-en"],[54,55,"pl-k"],[55,62,"pl-smi"]],[[5,6,"pl-k"]],[[4,72,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,23,"pl-c1"],[23,24,"pl-k"],[24,28,"pl-en"],[30,31,"pl-k"],[31,40,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[20,21,"pl-s"],[21,25,"pl-c1"],[25,26,"pl-s"]],[],[[0,40,"pl-mh"],[4,40,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,33,"pl-en"],[35,41,"pl-en"],[43,47,"pl-en"],[49,64,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,28,"pl-c1"],[30,32,"pl-c1"],[33,34,"pl-k"],[34,36,"pl-en"],[37,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[],[[4,7,"pl-k"],[8,21,"pl-smi"],[22,23,"pl-k"],[24,39,"pl-en"],[39,41,"pl-k"],[41,44,"pl-en"],[45,46,"pl-k"],[46,50,"pl-smi"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,21,"pl-en"],[21,23,"pl-k"],[23,28,"pl-en"]],[[8,9,"pl-k"],[9,17,"pl-en"],[18,22,"pl-en"],[22,24,"pl-k"],[24,27,"pl-en"]],[[8,9,"pl-k"],[9,13,"pl-en"],[14,23,"pl-en"],[23,25,"pl-k"],[25,35,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[26,39,"pl-smi"],[40,41,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,24,"pl-c1"],[24,25,"pl-k"],[25,31,"pl-en"],[33,34,"pl-k"],[34,38,"pl-en"],[39,41,"pl-c1"],[42,43,"pl-k"],[43,52,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,65,"pl-mh"],[4,65,"pl-en"],[30,31,"pl-s"],[31,34,"pl-c1"],[34,35,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[10,15,"pl-en"],[15,17,"pl-k"],[24,31,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,18,"pl-en"],[19,23,"pl-c1"],[25,26,"pl-c1"],[28,30,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-en"],[35,37,"pl-c1"],[39,41,"pl-c1"],[43,44,"pl-c1"],[46,47,"pl-c1"],[48,49,"pl-k"],[49,54,"pl-en"],[55,73,"pl-s"],[55,56,"pl-pds"],[72,73,"pl-pds"],[74,75,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,26,"pl-en"],[30,37,"pl-en"],[37,39,"pl-k"],[39,47,"pl-en"]],[],[[4,7,"pl-k"],[8,20,"pl-smi"],[21,22,"pl-k"],[23,26,"pl-smi"],[26,27,"pl-k"],[27,38,"pl-en"],[39,40,"pl-c1"],[42,49,"pl-en"],[49,51,"pl-k"],[51,58,"pl-en"],[59,60,"pl-k"]],[[4,14,"pl-en"]],[[8,20,"pl-smi"],[20,21,"pl-k"],[21,30,"pl-en"]],[[8,53,"pl-s"],[8,9,"pl-pds"],[52,53,"pl-pds"]],[],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[17,18,"pl-s"],[18,54,"pl-c1"],[54,55,"pl-s"]],[],[[0,1,"pl-s"],[1,21,"pl-c1"],[21,22,"pl-s"]],[],[],[[0,54,"pl-mh"],[4,54,"pl-en"]],[],[],[],[[0,1,"pl-s"],[1,39,"pl-c1"],[39,40,"pl-s"]],[[48,49,"pl-s"],[49,51,"pl-c1"],[51,52,"pl-s"]],[],[[36,37,"pl-s"],[43,44,"pl-s"],[48,49,"pl-s"],[49,51,"pl-c1"],[51,52,"pl-s"]],[],[],[],[],[],[],[],[],[],[[0,3,"pl-s"],[3,14,"pl-en"],[14,14,"pl-c1"]],[[0,72,"pl-c1"]],[[0,0,"pl-c1"]],[[0,70,"pl-c1"]],[[0,67,"pl-c1"]],[[0,67,"pl-c1"]],[[0,23,"pl-c1"]],[[0,54,"pl-c1"]],[[0,0,"pl-c1"]],[[0,33,"pl-c1"]],[[0,72,"pl-c1"]],[[0,31,"pl-c1"]],[[0,69,"pl-c1"]],[[0,28,"pl-c1"]],[[0,24,"pl-c1"]],[[0,0,"pl-c1"]],[[0,73,"pl-c1"]],[[0,34,"pl-c1"]],[[0,51,"pl-c1"]],[[0,58,"pl-c1"]],[[0,49,"pl-c1"]],[[0,0,"pl-c1"]],[[0,74,"pl-c1"]],[[0,69,"pl-c1"]],[[0,67,"pl-c1"]],[[0,34,"pl-c1"]],[[0,49,"pl-c1"]],[[0,72,"pl-c1"]],[[0,75,"pl-c1"]],[[0,34,"pl-c1"]],[[0,45,"pl-c1"]],[[0,0,"pl-c1"]],[[0,73,"pl-c1"]],[[0,74,"pl-c1"]],[[0,79,"pl-c1"]],[[0,36,"pl-c1"]],[[0,73,"pl-c1"]],[[0,0,"pl-c1"]],[[0,10,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[],[],[],[],[[0,54,"pl-mh"],[4,54,"pl-en"]],[],[[6,7,"pl-s"],[7,11,"pl-c1"],[11,12,"pl-s"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,30,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,23,"pl-en"],[25,26,"pl-k"],[26,32,"pl-en"],[33,34,"pl-c1"],[35,36,"pl-k"],[36,40,"pl-en"],[41,43,"pl-c1"],[44,45,"pl-k"],[45,50,"pl-en"],[51,53,"pl-c1"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,23,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,33,"pl-en"],[35,40,"pl-smi"],[42,46,"pl-en"],[47,51,"pl-c1"],[53,54,"pl-c1"],[56,57,"pl-c1"],[60,61,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[20,21,"pl-k"],[21,30,"pl-en"],[34,35,"pl-c1"],[35,36,"pl-k"],[36,41,"pl-en"],[43,44,"pl-k"],[44,50,"pl-en"],[51,52,"pl-c1"],[53,54,"pl-k"],[54,58,"pl-en"],[59,61,"pl-c1"],[62,63,"pl-k"],[63,68,"pl-en"],[69,70,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[28,29,"pl-s"],[29,35,"pl-c1"],[35,36,"pl-s"],[41,42,"pl-s"],[42,46,"pl-c1"],[46,47,"pl-s"]],[],[],[[0,54,"pl-mh"],[4,54,"pl-en"]],[],[[22,23,"pl-s"],[23,30,"pl-c1"],[30,31,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[18,27,"pl-en"],[29,35,"pl-en"],[37,41,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,16,"pl-smi"],[17,18,"pl-k"],[19,24,"pl-en"],[24,26,"pl-k"],[26,30,"pl-en"],[31,35,"pl-c1"],[37,38,"pl-c1"],[40,41,"pl-c1"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,21,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"]],[[8,17,"pl-en"],[17,19,"pl-k"],[19,22,"pl-en"],[24,25,"pl-k"],[25,32,"pl-en"],[33,37,"pl-en"],[37,39,"pl-k"],[39,43,"pl-en"],[44,45,"pl-k"],[45,53,"pl-en"],[54,62,"pl-smi"]],[[5,6,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,24,"pl-c1"],[24,25,"pl-k"],[25,30,"pl-en"],[32,33,"pl-k"],[33,42,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,33,"pl-en"],[35,41,"pl-en"],[43,47,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,61,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,18,"pl-en"],[19,23,"pl-c1"],[25,26,"pl-c1"],[28,29,"pl-c1"],[30,31,"pl-k"],[31,33,"pl-en"],[34,36,"pl-c1"],[38,39,"pl-c1"],[41,42,"pl-c1"],[44,45,"pl-c1"],[46,47,"pl-k"],[47,52,"pl-en"],[53,71,"pl-s"],[53,54,"pl-pds"],[70,71,"pl-pds"],[72,73,"pl-k"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,21,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"]],[[8,17,"pl-en"],[17,19,"pl-k"],[19,22,"pl-en"],[24,25,"pl-k"],[25,32,"pl-en"],[33,37,"pl-en"],[37,39,"pl-k"],[39,43,"pl-en"],[44,45,"pl-k"],[45,53,"pl-en"],[54,55,"pl-k"],[55,58,"pl-smi"]],[[5,6,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,24,"pl-c1"],[24,25,"pl-k"],[25,30,"pl-en"],[32,33,"pl-k"],[33,42,"pl-en"]],[],[[4,66,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,18,"pl-en"],[19,23,"pl-c1"],[25,27,"pl-c1"],[29,30,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-en"],[35,37,"pl-c1"],[39,40,"pl-c1"],[42,43,"pl-c1"],[45,46,"pl-c1"],[47,48,"pl-k"],[48,53,"pl-en"],[54,72,"pl-s"],[54,55,"pl-pds"],[71,72,"pl-pds"],[73,74,"pl-k"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,21,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"]],[[8,17,"pl-en"],[17,19,"pl-k"],[19,22,"pl-en"],[24,25,"pl-k"],[25,32,"pl-en"],[33,37,"pl-en"],[37,39,"pl-k"],[39,43,"pl-en"],[44,45,"pl-k"],[45,53,"pl-en"],[54,55,"pl-k"],[55,58,"pl-smi"]],[[5,6,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,24,"pl-c1"],[24,25,"pl-k"],[25,30,"pl-en"],[32,33,"pl-k"],[33,42,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,40,"pl-mh"],[4,40,"pl-en"]],[],[],[],[],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"],[7,7,"pl-c1"]],[[0,10,"pl-c1"]],[[0,37,"pl-c1"]],[[0,12,"pl-c1"]],[[0,41,"pl-c1"]],[[0,117,"pl-c1"]],[[0,117,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,99,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,99,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,99,"pl-c1"]],[[0,99,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,99,"pl-c1"]],[[0,138,"pl-c1"]],[[0,99,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,138,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[],[[0,1,"pl-s"],[22,23,"pl-s"],[23,24,"pl-s"],[24,70,"pl-corl"],[70,71,"pl-s"]],[],[[0,43,"pl-mh"],[3,43,"pl-en"],[3,4,"pl-s"],[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"],[10,11,"pl-s"],[11,12,"pl-s"],[12,32,"pl-corl"],[32,33,"pl-s"]],[],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"]],[],[],[[33,34,"pl-s"],[34,44,"pl-c1"],[44,45,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-smi"],[9,17,"pl-s"],[9,10,"pl-pds"],[16,17,"pl-pds"]],[[0,4,"pl-smi"],[9,16,"pl-smi"],[19,26,"pl-s"],[19,20,"pl-pds"],[25,26,"pl-pds"],[28,36,"pl-smi"],[40,47,"pl-s"],[40,41,"pl-pds"],[46,47,"pl-pds"]],[[0,4,"pl-smi"],[9,16,"pl-smi"],[19,27,"pl-s"],[19,20,"pl-pds"],[26,27,"pl-pds"],[29,37,"pl-smi"],[41,55,"pl-s"],[41,42,"pl-pds"],[54,55,"pl-pds"],[57,65,"pl-s"],[57,58,"pl-pds"],[64,65,"pl-pds"],[67,76,"pl-s"],[67,68,"pl-pds"],[75,76,"pl-pds"]],[[0,7,"pl-smi"],[10,17,"pl-s"],[10,11,"pl-pds"],[16,17,"pl-pds"]],[[0,3,"pl-s"]],[],[[0,34,"pl-mh"],[4,34,"pl-en"]],[],[[5,6,"pl-s"],[6,12,"pl-c1"],[12,13,"pl-s"],[19,20,"pl-s"],[20,24,"pl-c1"],[24,25,"pl-s"]],[],[[39,40,"pl-s"],[40,41,"pl-s"],[41,48,"pl-c1"],[48,49,"pl-s"],[49,50,"pl-s"],[50,51,"pl-s"],[51,74,"pl-corl"],[74,75,"pl-s"]],[[61,62,"pl-s"],[62,71,"pl-c1"],[71,72,"pl-s"]],[],[],[],[[15,16,"pl-s"],[16,20,"pl-c1"],[20,21,"pl-s"]],[],[],[],[[15,16,"pl-s"],[16,20,"pl-c1"],[20,21,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,14,"pl-en"],[14,16,"pl-k"],[16,33,"pl-en"],[35,41,"pl-en"],[41,43,"pl-k"],[53,61,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,55,"pl-c"],[4,6,"pl-c"]],[[4,56,"pl-c"],[4,6,"pl-c"]],[[4,42,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,23,"pl-en"],[24,28,"pl-c1"],[28,29,"pl-k"],[29,31,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-c1"],[35,37,"pl-c1"],[37,38,"pl-k"],[38,40,"pl-c1"],[40,41,"pl-k"],[41,43,"pl-c1"],[44,45,"pl-k"],[45,47,"pl-c1"],[47,48,"pl-k"],[48,50,"pl-c1"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,17,"pl-smi"],[17,18,"pl-k"],[18,29,"pl-en"],[30,31,"pl-c1"],[31,32,"pl-k"],[32,37,"pl-en"]],[[6,7,"pl-k"],[7,14,"pl-en"],[15,43,"pl-s"],[15,16,"pl-pds"],[42,43,"pl-pds"],[44,45,"pl-k"]],[[4,52,"pl-c"],[4,6,"pl-c"]],[[4,19,"pl-c"],[4,6,"pl-c"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,64,"pl-s"],[32,33,"pl-pds"],[63,64,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"]],[[40,41,"pl-s"],[41,55,"pl-c1"],[55,56,"pl-s"]],[],[[50,51,"pl-s"],[60,61,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,30,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,37,"pl-c1"],[39,41,"pl-c1"],[43,44,"pl-c1"],[46,47,"pl-c1"],[48,49,"pl-k"],[49,54,"pl-en"],[55,73,"pl-s"],[55,56,"pl-pds"],[72,73,"pl-pds"],[74,75,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,31,"pl-en"],[32,33,"pl-c1"],[33,34,"pl-k"],[34,38,"pl-en"],[41,42,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,78,"pl-s"],[33,34,"pl-pds"],[77,78,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[11,12,"pl-s"],[12,19,"pl-c1"],[19,20,"pl-s"],[63,64,"pl-s"],[64,68,"pl-c1"],[68,69,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,10,"pl-en"],[10,12,"pl-k"],[12,19,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,14,"pl-en"],[14,16,"pl-k"],[16,33,"pl-en"],[35,41,"pl-en"],[41,43,"pl-k"],[53,61,"pl-en"]],[[0,3,"pl-k"],[4,11,"pl-en"],[11,13,"pl-k"],[14,31,"pl-en"],[33,35,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,20,"pl-en"],[20,22,"pl-k"],[22,31,"pl-en"],[31,33,"pl-k"],[33,35,"pl-en"],[35,37,"pl-k"],[37,44,"pl-en"],[44,46,"pl-k"],[46,54,"pl-c1"]],[],[[4,55,"pl-c"],[4,6,"pl-c"]],[[4,56,"pl-c"],[4,6,"pl-c"]],[[4,42,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,23,"pl-en"],[24,28,"pl-c1"],[28,29,"pl-k"],[29,31,"pl-c1"],[31,32,"pl-k"],[32,34,"pl-c1"],[35,37,"pl-c1"],[37,38,"pl-k"],[38,40,"pl-c1"],[40,41,"pl-k"],[41,43,"pl-c1"],[44,45,"pl-k"],[45,47,"pl-c1"],[47,48,"pl-k"],[48,50,"pl-c1"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,17,"pl-smi"],[17,18,"pl-k"],[18,29,"pl-en"],[30,31,"pl-c1"],[31,32,"pl-k"],[32,37,"pl-en"]],[[6,7,"pl-k"],[7,14,"pl-en"],[15,43,"pl-s"],[15,16,"pl-pds"],[42,43,"pl-pds"],[44,45,"pl-k"]],[[6,7,"pl-k"],[7,18,"pl-en"],[19,21,"pl-smi"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,64,"pl-s"],[32,33,"pl-pds"],[63,64,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[45,46,"pl-s"],[46,60,"pl-c1"],[60,61,"pl-s"]],[],[],[],[],[],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"]],[[12,13,"pl-s"],[13,20,"pl-c1"],[20,21,"pl-s"]],[],[],[[0,53,"pl-mh"],[4,53,"pl-en"],[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,17,"pl-en"],[17,19,"pl-k"],[39,53,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,14,"pl-smi"],[15,16,"pl-k"],[17,36,"pl-en"]],[[8,56,"pl-s"],[8,9,"pl-pds"]],[[0,70,"pl-s"],[69,70,"pl-pds"]],[],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,28,"pl-en"],[28,30,"pl-k"],[30,35,"pl-en"],[36,67,"pl-s"],[36,37,"pl-pds"],[66,67,"pl-pds"],[69,70,"pl-k"],[70,76,"pl-smi"],[77,78,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,65,"pl-s"],[32,33,"pl-pds"],[64,65,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[20,21,"pl-s"],[21,29,"pl-c1"],[29,30,"pl-s"],[31,32,"pl-s"],[32,40,"pl-c1"],[40,41,"pl-s"]],[[0,1,"pl-s"],[1,19,"pl-c1"],[19,20,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[10,15,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,19,"pl-en"],[19,21,"pl-k"],[21,29,"pl-en"]],[[6,29,"pl-s"],[6,7,"pl-pds"],[28,29,"pl-pds"]],[[6,37,"pl-s"],[6,7,"pl-pds"],[36,37,"pl-pds"]],[[5,6,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,67,"pl-s"],[32,33,"pl-pds"],[66,67,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"],[21,22,"pl-s"],[22,30,"pl-c1"],[30,31,"pl-s"],[32,33,"pl-s"],[33,41,"pl-c1"],[41,42,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[10,24,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,78,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,14,"pl-smi"],[15,16,"pl-k"],[17,21,"pl-en"],[21,23,"pl-k"],[23,41,"pl-en"],[41,43,"pl-k"],[43,66,"pl-en"]],[[8,30,"pl-s"],[8,9,"pl-pds"],[29,30,"pl-pds"]],[[5,6,"pl-k"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[12,13,"pl-k"],[14,28,"pl-en"],[28,30,"pl-k"],[30,35,"pl-en"],[36,63,"pl-s"],[36,37,"pl-pds"],[62,63,"pl-pds"],[65,66,"pl-k"],[66,72,"pl-smi"],[73,74,"pl-k"]],[[4,14,"pl-en"],[15,18,"pl-smi"],[18,19,"pl-k"],[19,28,"pl-en"],[32,65,"pl-s"],[32,33,"pl-pds"],[64,65,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"]],[],[[9,10,"pl-s"],[10,15,"pl-c1"],[15,16,"pl-s"],[24,25,"pl-s"],[25,33,"pl-c1"],[33,34,"pl-s"]],[[0,1,"pl-s"],[1,5,"pl-c1"],[5,6,"pl-s"],[9,10,"pl-s"],[10,24,"pl-c1"],[24,25,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,26,"pl-en"],[26,28,"pl-k"],[29,33,"pl-c1"],[35,43,"pl-en"],[46,50,"pl-en"],[52,57,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,21,"pl-en"],[21,23,"pl-k"],[23,28,"pl-en"],[29,31,"pl-en"],[31,33,"pl-k"],[33,39,"pl-en"],[40,41,"pl-k"],[41,42,"pl-c1"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,58,"pl-en"],[59,61,"pl-smi"],[62,63,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[26,30,"pl-en"],[30,32,"pl-k"],[32,36,"pl-en"],[37,38,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,68,"pl-s"],[33,34,"pl-pds"],[67,68,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[33,34,"pl-s"],[38,39,"pl-s"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,28,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,72,"pl-c"],[4,6,"pl-c"]],[[4,25,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[26,30,"pl-en"],[30,32,"pl-k"],[32,36,"pl-en"],[37,38,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,78,"pl-s"],[33,34,"pl-pds"],[77,78,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[],[],[[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,33,"pl-en"],[35,41,"pl-en"],[43,47,"pl-en"],[49,64,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,28,"pl-c1"],[30,32,"pl-c1"],[33,34,"pl-k"],[34,36,"pl-en"],[37,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,42,"pl-c1"],[44,45,"pl-c1"],[47,48,"pl-c1"],[49,50,"pl-k"],[50,55,"pl-en"],[56,74,"pl-s"],[56,57,"pl-pds"],[73,74,"pl-pds"],[75,76,"pl-k"]],[],[[4,7,"pl-k"],[8,21,"pl-smi"],[22,23,"pl-k"],[24,39,"pl-en"],[39,41,"pl-k"],[41,44,"pl-en"],[45,46,"pl-k"],[46,50,"pl-smi"]],[[8,9,"pl-k"],[9,16,"pl-en"],[17,21,"pl-en"],[21,23,"pl-k"],[23,27,"pl-en"]],[[8,9,"pl-k"],[9,17,"pl-en"],[18,22,"pl-en"],[22,24,"pl-k"],[24,27,"pl-en"]],[[8,9,"pl-k"],[9,13,"pl-en"],[14,23,"pl-en"],[23,25,"pl-k"],[25,35,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,25,"pl-en"],[26,39,"pl-smi"],[40,41,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,23,"pl-c1"],[23,24,"pl-k"],[24,29,"pl-en"],[31,32,"pl-k"],[32,38,"pl-en"],[39,40,"pl-c1"],[41,42,"pl-k"],[42,46,"pl-en"],[47,49,"pl-c1"],[50,51,"pl-k"],[51,60,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"]],[],[[0,49,"pl-mh"],[4,49,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,16,"pl-en"],[16,18,"pl-k"],[24,30,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-en"],[20,24,"pl-c1"],[26,27,"pl-c1"],[29,31,"pl-c1"],[32,33,"pl-k"],[33,35,"pl-en"],[36,38,"pl-c1"],[40,41,"pl-c1"],[43,44,"pl-c1"],[46,47,"pl-c1"],[48,49,"pl-k"],[49,54,"pl-en"],[55,73,"pl-s"],[55,56,"pl-pds"],[72,73,"pl-pds"],[74,75,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,31,"pl-en"],[32,33,"pl-c1"],[33,34,"pl-k"],[34,39,"pl-en"],[41,42,"pl-k"],[42,48,"pl-en"],[49,50,"pl-c1"],[51,52,"pl-k"],[52,56,"pl-en"],[57,58,"pl-c1"],[60,61,"pl-k"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,29,"pl-en"],[33,78,"pl-s"],[33,34,"pl-pds"],[77,78,"pl-pds"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"],[51,52,"pl-s"],[52,60,"pl-c1"],[60,61,"pl-s"]],[[9,10,"pl-s"],[10,24,"pl-c1"],[24,25,"pl-s"]],[[23,24,"pl-s"],[24,28,"pl-c1"],[28,29,"pl-s"]],[],[[0,53,"pl-mh"],[4,53,"pl-en"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,20,"pl-en"],[22,28,"pl-en"],[30,34,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,31,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,17,"pl-c1"],[17,18,"pl-k"],[18,23,"pl-en"],[25,26,"pl-k"],[26,33,"pl-en"],[34,36,"pl-c1"],[37,38,"pl-k"],[38,45,"pl-en"],[46,48,"pl-c1"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"],[28,37,"pl-en"],[37,39,"pl-k"],[39,42,"pl-en"],[44,45,"pl-k"],[45,52,"pl-en"],[53,57,"pl-en"],[57,59,"pl-k"],[59,65,"pl-en"],[67,68,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,28,"pl-c1"],[28,29,"pl-k"],[29,36,"pl-en"],[38,39,"pl-k"],[39,48,"pl-en"]],[],[[4,44,"pl-c"],[4,6,"pl-c"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,22,"pl-c1"],[22,23,"pl-k"],[23,30,"pl-en"]],[[4,7,"pl-k"],[8,13,"pl-smi"],[14,15,"pl-k"],[16,21,"pl-smi"],[21,22,"pl-k"],[22,27,"pl-en"],[28,37,"pl-en"],[37,39,"pl-k"],[39,42,"pl-en"],[44,45,"pl-k"],[45,52,"pl-en"],[53,57,"pl-en"],[57,59,"pl-k"],[59,63,"pl-en"],[65,66,"pl-k"]],[[4,14,"pl-en"],[15,20,"pl-smi"],[22,23,"pl-c1"],[23,24,"pl-k"],[24,29,"pl-en"],[31,32,"pl-k"],[32,39,"pl-en"],[40,42,"pl-c1"],[43,44,"pl-k"],[44,51,"pl-en"],[52,54,"pl-c1"],[55,56,"pl-k"],[56,65,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"],[19,20,"pl-s"],[20,28,"pl-c1"],[28,29,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,14,"pl-en"],[14,16,"pl-k"],[16,33,"pl-en"],[35,43,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,16,"pl-c1"],[16,17,"pl-k"],[17,22,"pl-en"],[25,26,"pl-k"],[27,29,"pl-c1"],[29,30,"pl-k"],[30,37,"pl-en"],[40,41,"pl-k"],[42,44,"pl-c1"],[44,45,"pl-k"],[45,52,"pl-en"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,33,"pl-en"],[37,43,"pl-c1"]],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,14,"pl-en"],[14,16,"pl-k"],[16,33,"pl-en"],[35,43,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,21,"pl-c1"],[21,22,"pl-k"],[22,29,"pl-en"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,31,"pl-en"],[35,36,"pl-c1"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,33,"pl-en"],[37,40,"pl-c1"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,33,"pl-en"],[37,43,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,18,"pl-en"],[18,20,"pl-k"],[21,25,"pl-en"],[27,33,"pl-en"],[35,41,"pl-en"],[44,47,"pl-en"],[47,49,"pl-k"],[49,66,"pl-en"],[68,76,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-k"],[12,16,"pl-smi"],[17,18,"pl-k"],[19,25,"pl-c1"],[25,26,"pl-k"],[26,33,"pl-en"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,31,"pl-en"],[35,36,"pl-c1"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,33,"pl-en"],[36,37,"pl-k"],[38,44,"pl-en"],[44,46,"pl-k"],[46,49,"pl-en"],[50,54,"pl-en"],[56,58,"pl-k"],[59,62,"pl-k"],[64,66,"pl-c1"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[19,20,"pl-k"],[20,33,"pl-en"],[36,37,"pl-k"],[38,44,"pl-en"],[44,46,"pl-k"],[46,49,"pl-en"],[50,56,"pl-en"],[58,60,"pl-k"],[61,64,"pl-k"],[66,68,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[0,40,"pl-mh"],[4,40,"pl-en"],[34,35,"pl-s"],[35,39,"pl-c1"],[39,40,"pl-s"]],[],[[69,70,"pl-s"],[70,74,"pl-c1"],[74,75,"pl-s"]],[[21,22,"pl-s"],[22,26,"pl-c1"],[26,27,"pl-s"]],[],[[22,23,"pl-s"],[23,27,"pl-c1"],[27,28,"pl-s"]],[],[[42,43,"pl-s"],[43,54,"pl-c1"],[54,55,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"],[7,7,"pl-c1"]],[[0,10,"pl-c1"]],[[0,41,"pl-c1"]],[[0,12,"pl-c1"]],[[0,39,"pl-c1"]],[[0,115,"pl-c1"]],[[0,115,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,99,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,99,"pl-c1"]],[[0,99,"pl-c1"]],[[0,99,"pl-c1"]],[[0,99,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,136,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[],[[0,1,"pl-s"],[22,23,"pl-s"],[23,24,"pl-s"],[24,70,"pl-corl"],[70,71,"pl-s"]],[],[[0,50,"pl-mh"],[3,50,"pl-en"],[3,4,"pl-s"],[4,5,"pl-s"],[5,13,"pl-c1"],[13,14,"pl-s"],[14,15,"pl-s"],[15,16,"pl-s"],[16,40,"pl-corl"],[40,41,"pl-s"]],[],[[0,1,"pl-s"],[1,9,"pl-c1"],[9,10,"pl-s"]],[],[],[],[],[[33,34,"pl-s"],[34,44,"pl-c1"],[44,45,"pl-s"]],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-smi"],[9,17,"pl-s"],[9,10,"pl-pds"],[16,17,"pl-pds"]],[[0,8,"pl-smi"],[11,18,"pl-s"],[11,12,"pl-pds"],[17,18,"pl-pds"]],[[0,4,"pl-smi"],[9,16,"pl-smi"],[19,26,"pl-s"],[19,20,"pl-pds"],[25,26,"pl-pds"],[28,36,"pl-smi"],[40,47,"pl-s"],[40,41,"pl-pds"],[46,47,"pl-pds"]],[[0,3,"pl-s"]],[],[[0,34,"pl-mh"],[4,34,"pl-en"]],[],[[9,10,"pl-s"],[10,14,"pl-c1"],[14,15,"pl-s"],[23,24,"pl-s"],[24,32,"pl-c1"],[32,33,"pl-s"]],[[45,46,"pl-s"],[46,54,"pl-c1"],[54,55,"pl-s"]],[[14,15,"pl-s"],[15,29,"pl-c1"],[29,30,"pl-s"],[39,40,"pl-s"],[40,44,"pl-c1"],[44,45,"pl-s"]],[[5,6,"pl-s"],[6,14,"pl-c1"],[14,15,"pl-s"],[23,24,"pl-s"],[24,29,"pl-c1"],[29,30,"pl-s"]],[],[[13,14,"pl-s"],[14,22,"pl-c1"],[22,23,"pl-s"]],[],[[0,36,"pl-mh"],[4,36,"pl-en"],[4,5,"pl-s"],[5,13,"pl-c1"],[13,14,"pl-s"]],[],[[50,51,"pl-s"],[51,56,"pl-c1"],[56,57,"pl-s"]],[[49,50,"pl-s"],[50,58,"pl-c1"],[58,59,"pl-s"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,12,"pl-en"],[12,14,"pl-k"],[15,23,"pl-en"],[25,30,"pl-en"],[32,41,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[10,11,"pl-k"],[12,17,"pl-en"],[18,19,"pl-k"],[20,45,"pl-s"],[20,21,"pl-pds"],[44,45,"pl-pds"],[45,46,"pl-k"],[46,51,"pl-en"],[53,54,"pl-k"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[10,11,"pl-k"],[12,17,"pl-en"],[18,19,"pl-k"],[20,45,"pl-s"],[20,21,"pl-pds"],[44,45,"pl-pds"],[45,46,"pl-k"],[46,51,"pl-en"],[53,54,"pl-k"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,15,"pl-smi"],[15,16,"pl-k"],[16,29,"pl-en"],[30,39,"pl-en"],[39,41,"pl-k"],[41,44,"pl-c1"]],[],[[4,7,"pl-k"],[8,16,"pl-smi"],[17,18,"pl-k"],[19,21,"pl-smi"],[22,23,"pl-k"],[24,26,"pl-smi"]],[[4,14,"pl-en"],[15,23,"pl-smi"],[25,33,"pl-en"],[33,35,"pl-k"],[35,47,"pl-en"],[48,55,"pl-c1"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[15,16,"pl-s"],[45,46,"pl-s"],[46,47,"pl-s"],[47,64,"pl-en"],[64,65,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,20,"pl-en"],[22,28,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,22,"pl-en"],[23,24,"pl-k"],[25,47,"pl-s"],[25,26,"pl-pds"],[46,47,"pl-pds"],[47,48,"pl-k"],[48,53,"pl-en"],[55,56,"pl-k"]],[[4,7,"pl-k"],[8,11,"pl-smi"],[11,12,"pl-k"],[13,22,"pl-en"],[23,24,"pl-k"],[25,47,"pl-s"],[25,26,"pl-pds"],[46,47,"pl-pds"],[47,48,"pl-k"],[48,53,"pl-en"],[55,56,"pl-k"]],[[4,7,"pl-k"],[8,12,"pl-smi"],[13,14,"pl-k"],[15,18,"pl-smi"],[19,20,"pl-k"],[21,24,"pl-smi"]],[[4,14,"pl-en"],[15,19,"pl-smi"],[21,26,"pl-c1"],[26,27,"pl-k"],[27,34,"pl-en"],[36,37,"pl-k"],[37,46,"pl-en"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[30,31,"pl-s"],[31,36,"pl-c1"],[36,37,"pl-s"],[71,72,"pl-s"],[78,79,"pl-s"]],[[13,14,"pl-s"],[14,19,"pl-c1"],[19,20,"pl-s"],[45,46,"pl-s"],[46,54,"pl-c1"],[54,55,"pl-s"]],[],[[0,1,"pl-s"],[1,18,"pl-en"],[18,19,"pl-s"],[21,64,"pl-corl"]],[],[[0,56,"pl-mh"],[4,56,"pl-en"]],[],[],[[27,28,"pl-s"],[28,31,"pl-c1"],[31,32,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,8,"pl-en"],[8,10,"pl-k"],[11,20,"pl-en"],[22,28,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,22,"pl-en"],[22,24,"pl-k"],[24,27,"pl-c1"]],[[4,11,"pl-en"],[12,14,"pl-smi"],[14,15,"pl-k"],[15,26,"pl-en"],[27,28,"pl-c1"],[28,29,"pl-k"],[29,32,"pl-en"],[35,36,"pl-k"],[36,42,"pl-en"]],[[4,14,"pl-en"],[15,17,"pl-smi"],[17,18,"pl-k"],[18,32,"pl-en"],[33,34,"pl-c1"],[34,35,"pl-k"],[35,39,"pl-en"],[42,43,"pl-k"],[45,47,"pl-smi"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[[13,14,"pl-s"],[14,22,"pl-c1"],[22,23,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,3,"pl-k"],[4,12,"pl-en"],[12,14,"pl-k"],[15,23,"pl-en"],[25,30,"pl-en"]],[],[[0,2,"pl-k"],[3,7,"pl-en"],[10,12,"pl-k"],[13,19,"pl-en"],[19,21,"pl-k"],[21,27,"pl-en"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,18,"pl-en"],[18,20,"pl-k"],[20,37,"pl-en"],[38,41,"pl-en"],[41,43,"pl-k"],[43,46,"pl-c1"]],[[4,7,"pl-k"],[8,10,"pl-smi"],[11,12,"pl-k"],[13,15,"pl-smi"],[16,17,"pl-k"],[18,26,"pl-en"],[26,28,"pl-k"],[28,37,"pl-en"],[38,41,"pl-c1"]],[[4,14,"pl-en"],[15,17,"pl-smi"],[19,21,"pl-smi"]],[],[[4,6,"pl-en"]],[],[[0,3,"pl-s"]],[],[],[[0,40,"pl-mh"],[3,40,"pl-en"],[3,4,"pl-s"],[4,5,"pl-s"],[5,8,"pl-c1"],[8,9,"pl-s"],[9,10,"pl-s"],[10,11,"pl-s"],[11,30,"pl-corl"],[30,31,"pl-s"]],[],[[57,58,"pl-s"],[58,62,"pl-c1"],[62,63,"pl-s"]],[[39,40,"pl-s"],[40,53,"pl-c1"],[53,54,"pl-s"]],[],[[58,59,"pl-s"],[59,72,"pl-c1"],[72,73,"pl-s"]],[],[],[],[],[[0,1,"pl-s"],[1,4,"pl-c1"],[4,5,"pl-s"],[32,33,"pl-s"],[33,37,"pl-c1"],[37,38,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-s"],[2,10,"pl-c1"],[10,11,"pl-s"],[11,12,"pl-s"],[12,13,"pl-s"],[13,37,"pl-corl"],[37,38,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"],[7,7,"pl-c1"]],[[0,10,"pl-c1"]],[[0,45,"pl-c1"]],[[0,37,"pl-c1"]],[[0,18,"pl-c1"]],[[0,2,"pl-c1"]],[[0,20,"pl-c1"]],[[0,31,"pl-c1"]],[[0,0,"pl-c1"]],[[0,33,"pl-c1"]],[[0,56,"pl-c1"]],[[0,40,"pl-c1"]],[[0,0,"pl-c1"]],[[0,27,"pl-c1"]],[[0,60,"pl-c1"]],[[0,0,"pl-c1"]],[[0,36,"pl-c1"]],[[0,78,"pl-c1"]],[[0,0,"pl-c1"]],[[0,35,"pl-c1"]],[[0,52,"pl-c1"]],[[0,33,"pl-c1"]],[[0,27,"pl-c1"]],[[0,7,"pl-c1"]],[[0,0,"pl-c1"]],[[0,46,"pl-c1"]],[[0,15,"pl-c1"]],[[0,57,"pl-c1"]],[[0,37,"pl-c1"]],[[0,6,"pl-c1"]],[[0,0,"pl-c1"]],[[0,10,"pl-c1"]],[[0,1,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-smi"],[9,17,"pl-s"],[9,10,"pl-pds"],[16,17,"pl-pds"]],[[0,3,"pl-smi"],[8,15,"pl-smi"],[18,25,"pl-s"],[18,19,"pl-pds"],[24,25,"pl-pds"],[27,35,"pl-smi"],[39,44,"pl-s"],[39,40,"pl-pds"],[43,44,"pl-pds"]],[[0,4,"pl-smi"],[9,16,"pl-smi"],[19,26,"pl-s"],[19,20,"pl-pds"],[25,26,"pl-pds"],[28,36,"pl-smi"],[40,47,"pl-s"],[40,41,"pl-pds"],[46,47,"pl-pds"]],[[0,8,"pl-smi"],[13,20,"pl-smi"],[23,30,"pl-s"],[23,24,"pl-pds"],[29,30,"pl-pds"]],[[0,3,"pl-s"]]],"colorizedLines":null}},"title":"jiff/COMPARE.md at master · jif-oai/jiff","appPayload":{},"meta":{"title":"jiff/COMPARE.md at master · jif-oai/jiff"}}</script>
  <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/jif-oai/jiff" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d" data-component="SplitPageLayout" data-has-sidebar="true"><div class="prc-PageLayout-SidebarWrapper-kLG4B CopilotSidePanelSidebar-module__SidePanel__L3O0C CopilotSidePanelSidebar-module__HiddenSidePanel__TBRGn" style="--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="end" data-sticky="true" data-responsive-variant="fullscreen"><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-SidebarVerticalDivider-0Rl0V" data-component="PageLayout.VerticalDivider" data-variant="line" data-position="end" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="450" aria-valuemax="768" aria-valuenow="544" aria-valuetext="Pane width 544 pixels" tabindex="0"></div></div><div class="prc-PageLayout-Sidebar-iciWg" data-component="SplitPageLayout.Sidebar" data-resizable="true" style="--spacing:var(--spacing-normal);--pane-min-width:450px;--pane-max-width:768px;--pane-width-custom:544px;--pane-width-size:var(--pane-width-custom);--pane-width:544px"><div class="height-full" data-testid="copilot-code-view-side-panel"><div id="copilot-side-panel-content" class="height-full"></div></div></div></div><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div id="repos-file-tree-sidebar" class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-component="PageLayout.HorizontalDivider" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-component="SplitPageLayout.Pane" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-component="PageLayout.VerticalDivider" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div data-component="SplitPageLayout.Content" class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" id="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_4lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_4lla9lik5_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/jif-oai/jiff/tree/master" data-discover="true">jiff</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">COMPARE.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lla9lik5_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_1cpla9lik5_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_1cpla9lik5_ _R_1cpla9lik5H1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_1cpla9lik5H1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7p9la9lik5_" id="_R_99la9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7p9la9lik5_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7pdla9lik5_" id="_R_9dla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7pdla9lik5_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/jif-oai/jiff/commits/master/COMPARE.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/jif-oai/jiff/commits/master/COMPARE.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_4mlala9lik5_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_4mlala9lik5_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="55.5 KB" style="--truncate-max-width:100%"><span>1278 lines (1017 loc) · 55.5 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/jif-oai/jiff/tree/master" data-discover="true">jiff</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">COMPARE.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lcpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lcpala9lik5_">Copy path</span></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small" data-component="SegmentedControl"><li class="prc-SegmentedControl-Item-tSCQh" data-selected="" data-component="SegmentedControl.Button"><button aria-pressed="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="55.5 KB" style="--truncate-max-width:100%"><span>1278 lines (1017 loc) · 55.5 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div class="prc-ButtonGroup-Item-PqvDl"><a data-component="LinkButton" href="https://github.com/jif-oai/jiff/raw/refs/heads/master/COMPARE.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_qaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_qaucpala9lik5_">Copy raw file</span></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_eaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_eaucpala9lik5_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3ucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_3ucpala9lik5_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_fkecpala9lik5_" id="_R_kecpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fkecpala9lik5_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true" containertiming="hpc"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">Comparison with other Rust datetime crates</h1><a id="user-content-comparison-with-other-rust-datetime-crates" class="anchor" aria-label="Permalink: Comparison with other Rust datetime crates" href="#comparison-with-other-rust-datetime-crates"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">This document is meant to be a comparison between Jiff and each of the other
prominent open source datetime libraries for Rust. If you feel like there is a
library missing from this list, please file an issue about it. I would prefer
to only add libraries to this list that are being used in production or have a
substantial number of users.</p>
<p dir="auto">The goal of this document is to be as <em>descriptive</em> and <em>substantively
complete</em> as possible. For example, "Chrono has a better API design than Jiff"
would be a pretty vague value judgment that someone could easily disagree with.
But, "Chrono allows using a zone-aware datetime type that is <code>Copy</code> while Jiff
does not" would be a factual comparison that someone might use to <em>support</em> an
opinion that Chrono's API design is better than Jiff's. In other words, this
document should provide the "facts of comparison" but refrain from assigning
value judgments.</p>
<p dir="auto">In terms of completeness, it is probably not realistic to expect 100%
completion here. We aren't hunting for Korok Seeds. Instead, this document
aims for <em>substantive</em> completion. That is, if there's a point of difference
between Jiff and another library that would likely influence someone's decision
of which library to use, and can be articulated descriptively, then it should
probably be in this document.</p>
<p dir="auto">The current status of this document is that it is both <em>incomplete</em> and
<em>biased</em>. That is, this first draft was written by the author of Jiff without
any input from other crate maintainers. (To other crate maintainers: I welcome
feedback. Even if it's just filing an issue.)</p>
<p dir="auto">Note that this document contains many code snippets. They can be tested with
<code>cargo test --doc _documentation::comparison</code> from the root of this repository.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto"><a href="https://docs.rs/chrono" rel="nofollow"><code>chrono</code></a> (v0.4.38)</h2><a id="user-content-chrono-v0438" class="anchor" aria-label="Permalink: chrono (v0.4.38)" href="#chrono-v0438"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Chrono is a Rust datetime library that provides a time zone aware datetime
type.</p>
<p dir="auto">For the following comparisons, a <code>Cargo.toml</code> with the following dependencies
should be able to run any of the programs in this section:</p>
<div class="highlight highlight-source-toml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="anyhow = &quot;1.0.81&quot;
chrono = &quot;0.4.38&quot;
chrono-tz = { version = &quot;0.9.0&quot;, features = [&quot;serde&quot;] }
jiff = { version = &quot;0.2.0&quot;, features = [&quot;serde&quot;] }
serde = &quot;1.0.203&quot;
serde_json = &quot;1.0.117&quot;
tzfile = &quot;0.1.3&quot;"><pre><span class="pl-smi">anyhow</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.81<span class="pl-pds">"</span></span>
<span class="pl-smi">chrono</span> = <span class="pl-s"><span class="pl-pds">"</span>0.4.38<span class="pl-pds">"</span></span>
<span class="pl-smi">chrono-tz</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.9.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>serde<span class="pl-pds">"</span></span>] }
<span class="pl-smi">jiff</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.2.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>serde<span class="pl-pds">"</span></span>] }
<span class="pl-smi">serde</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.203<span class="pl-pds">"</span></span>
<span class="pl-smi">serde_json</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.117<span class="pl-pds">"</span></span>
<span class="pl-smi">tzfile</span> = <span class="pl-s"><span class="pl-pds">"</span>0.1.3<span class="pl-pds">"</span></span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Time zone database integration</h3><a id="user-content-time-zone-database-integration" class="anchor" aria-label="Permalink: Time zone database integration" href="#time-zone-database-integration"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Jiff gives you automatic integration with your copy of the Time Zone Database.
On Unix, it's usually found at <code>/usr/share/zoneinfo</code>. On Windows, since there
is no canonical location, Jiff will depend on <code>jiff-tzdb</code> by default, which
will embed the entire database into your binary. Jiff hides these details from
you. For example, to convert a civil time into an absolute time in a particular
time zone:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::civil::date;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = date(2024, 6, 30).at(9, 46, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    assert_eq!(zdt.to_string(), &quot;2024-06-30T09:46:00-04:00[America/New_York]&quot;);
    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">6</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">9</span><span class="pl-kos">,</span> <span class="pl-c1">46</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-06-30T09:46:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">For Chrono, one recommended option is to use the
<a href="https://docs.rs/chrono-tz" rel="nofollow"><code>chrono-tz</code></a> crate:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::TimeZone;
use chrono_tz::America::New_York;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = New_York.with_ymd_and_hms(2024, 6, 30, 9, 46, 0)
        .single()
        .context(&quot;invalid naive time&quot;)?;
    assert_eq!(zdt.to_string(), &quot;2024-06-30 09:46:00 EDT&quot;);
    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-v">TimeZone</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono_tz<span class="pl-kos">::</span><span class="pl-smi">America</span><span class="pl-kos">::</span><span class="pl-v">New_York</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-v">New_York</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">6</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">9</span><span class="pl-kos">,</span> <span class="pl-c1">46</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">single</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid naive time"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-06-30 09:46:00 EDT"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><code>chrono-tz</code> works by embedding an entire copy of the Time Zone Database into
your binary, where each time zone is represented as a Rust value that can be
imported via <code>use</code>. A disadvantage of this approach is that you're reliant on
<code>chrono-tz</code> updates to get the most recent time zone information. An advantage
of this approach is that you never need to worry about an end user's system
state. Another advantage is that this allows a <code>TimeZone</code> trait implementation
to be <code>Copy</code> via a <code>&amp;Tz</code>, and that in turn allows a <code>chrono::DateTime</code> to be
<code>Copy</code>. In contrast, in Jiff, a <code>TimeZone</code> is never <code>Copy</code>. Since a <code>Zoned</code>
embeds a <code>TimeZone</code>, a <code>Zoned</code> is never <code>Copy</code> either.</p>
<p dir="auto">Another recommended option is the <a href="https://docs.rs/tzfile" rel="nofollow"><code>tzfile</code></a> crate.
Unlike <code>chrono-tz</code>, the <code>tzfile</code> crate will try to read time zone data from
your system's copy of the Time Zone Database.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::TimeZone;
use tzfile::Tz;

#[cfg(unix)]
fn main() -&gt; anyhow::Result&lt;()&gt; {
    let tz = Tz::named(&quot;America/New_York&quot;)?;
    let zdt = (&amp;tz).with_ymd_and_hms(2024, 6, 30, 9, 46, 0)
        .single()
        .context(&quot;invalid naive time&quot;)?;
    assert_eq!(zdt.to_string(), &quot;2024-06-30 09:46:00 EDT&quot;);
    Ok(())
}

// `tzfile` exposes a platform specific API, which means
// users of the crate have to deal with platform differences
// themselves.
#[cfg(not(unix))]
fn main() -&gt; anyhow::Result&lt;()&gt; {
    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-v">TimeZone</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> tzfile<span class="pl-kos">::</span><span class="pl-v">Tz</span><span class="pl-kos">;</span>

<span class="pl-c1">#<span class="pl-kos">[</span>cfg<span class="pl-kos">(</span>unix<span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> tz = <span class="pl-smi">Tz</span><span class="pl-kos">::</span><span class="pl-en">named</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt = <span class="pl-kos">(</span><span class="pl-c1">&amp;</span>tz<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">6</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">9</span><span class="pl-kos">,</span> <span class="pl-c1">46</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">single</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid naive time"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-06-30 09:46:00 EDT"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span>

<span class="pl-c">// `tzfile` exposes a platform specific API, which means</span>
<span class="pl-c">// users of the crate have to deal with platform differences</span>
<span class="pl-c">// themselves.</span>
<span class="pl-c1">#<span class="pl-kos">[</span>cfg<span class="pl-kos">(</span>not<span class="pl-kos">(</span>unix<span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Note though that at time of writing (2024-07-11), <code>tzfile::Tz::named</code> will
read and parse the corresponding time zone rules from disk on every call.
Conversely, in Jiff, all time zone lookups by name are cached. This may or may
not matter for your use case.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff losslessly roundtrips time zone aware datetimes</h3><a id="user-content-jiff-losslessly-roundtrips-time-zone-aware-datetimes" class="anchor" aria-label="Permalink: Jiff losslessly roundtrips time zone aware datetimes" href="#jiff-losslessly-roundtrips-time-zone-aware-datetimes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">In Jiff, with <code>serde</code> support enabled, one can serialize and deserialize a
<code>Zoned</code> value losslessly. This means that, after deserialization, you can
expect it to still perform DST arithmetic:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, ToSpan, Zoned};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = date(2024, 3, 10).at(1, 59, 59, 0).in_tz(&quot;America/New_York&quot;)?;

    let json = serde_json::to_string_pretty(&amp;zdt)?;
    assert_eq!(json, &quot;\&quot;2024-03-10T01:59:59-05:00[America/New_York]\&quot;&quot;);

    let got: Zoned = serde_json::from_str(&amp;json)?;
    assert_eq!(got.to_string(), &quot;2024-03-10T01:59:59-05:00[America/New_York]&quot;);
    let next = got.checked_add(1.minute())?;
    assert_eq!(next.to_string(), &quot;2024-03-10T03:00:59-04:00[America/New_York]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Zoned</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> json = serde_json<span class="pl-kos">::</span><span class="pl-en">to_string_pretty</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>json<span class="pl-kos">,</span> <span class="pl-s">"<span class="pl-cce">\"</span>2024-03-10T01:59:59-05:00[America/New_York]<span class="pl-cce">\"</span>"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> got<span class="pl-kos">:</span> <span class="pl-smi">Zoned</span> = serde_json<span class="pl-kos">::</span><span class="pl-en">from_str</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>json<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>got<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10T01:59:59-05:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> next = got<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">minute</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>next<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10T03:00:59-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Notice that when we add a minute, it jumps to <code>03:00</code> civil time because of the
transition into daylight saving time in my selected time zone. Notice also the
offset change from <code>-05</code> to <code>-04</code>.</p>
<p dir="auto">Compare this with Chrono which also supports <code>serde</code>, but not with <code>chrono-tz</code>
or <code>tzfile</code>. One option is to use its <code>Local</code> implementation of its <code>TimeZone</code>
trait:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::{DateTime, FixedOffset, Local, TimeDelta, TimeZone};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = Local.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)
        .single()
        .context(&quot;invalid naive time&quot;)?;

    let json = serde_json::to_string_pretty(&amp;zdt)?;
    // Chrono only serializes the offset, which makes lossless
    // deserialization impossible. Chrono loses the time zone
    // information.
    assert_eq!(json, &quot;\&quot;2024-03-10T01:59:59-05:00\&quot;&quot;);

    // The serialized datetime has no time zone information,
    // so unless there is some out-of-band information saying
    // what its time zone is, we're forced to use a fixed offset:
    let got: DateTime&lt;FixedOffset&gt; = serde_json::from_str(&amp;json)?;
    assert_eq!(got.to_string(), &quot;2024-03-10 01:59:59 -05:00&quot;);
    let next = got.checked_add_signed(TimeDelta::minutes(1))
        .context(&quot;arithmetic failed&quot;)?;
    // This is correct for fixed offset, but it's no longer
    // DST aware.
    assert_eq!(next.to_string(), &quot;2024-03-10 02:00:59 -05:00&quot;);

    // We could deserialize into a `DateTime&lt;Local&gt;`, but this
    // requires knowing that the time zone of the datetime matches
    // local time zone. Which you might know. But you might not.
    let got: DateTime&lt;Local&gt; = serde_json::from_str(&amp;json)?;
    assert_eq!(got.to_string(), &quot;2024-03-10 01:59:59 -05:00&quot;);
    let next = got.checked_add_signed(TimeDelta::minutes(1))
        .context(&quot;arithmetic failed&quot;)?;
    assert_eq!(next.to_string(), &quot;2024-03-10 03:00:59 -04:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">DateTime</span><span class="pl-kos">,</span> <span class="pl-v">FixedOffset</span><span class="pl-kos">,</span> <span class="pl-v">Local</span><span class="pl-kos">,</span> <span class="pl-v">TimeDelta</span><span class="pl-kos">,</span> <span class="pl-v">TimeZone</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-v">Local</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">single</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid naive time"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> json = serde_json<span class="pl-kos">::</span><span class="pl-en">to_string_pretty</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// Chrono only serializes the offset, which makes lossless</span>
    <span class="pl-c">// deserialization impossible. Chrono loses the time zone</span>
    <span class="pl-c">// information.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>json<span class="pl-kos">,</span> <span class="pl-s">"<span class="pl-cce">\"</span>2024-03-10T01:59:59-05:00<span class="pl-cce">\"</span>"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// The serialized datetime has no time zone information,</span>
    <span class="pl-c">// so unless there is some out-of-band information saying</span>
    <span class="pl-c">// what its time zone is, we're forced to use a fixed offset:</span>
    <span class="pl-k">let</span> got<span class="pl-kos">:</span> <span class="pl-smi">DateTime</span><span class="pl-kos">&lt;</span><span class="pl-smi">FixedOffset</span><span class="pl-kos">&gt;</span> = serde_json<span class="pl-kos">::</span><span class="pl-en">from_str</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>json<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>got<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 01:59:59 -05:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> next = got<span class="pl-kos">.</span><span class="pl-en">checked_add_signed</span><span class="pl-kos">(</span><span class="pl-smi">TimeDelta</span><span class="pl-kos">::</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"arithmetic failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// This is correct for fixed offset, but it's no longer</span>
    <span class="pl-c">// DST aware.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>next<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 02:00:59 -05:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// We could deserialize into a `DateTime&lt;Local&gt;`, but this</span>
    <span class="pl-c">// requires knowing that the time zone of the datetime matches</span>
    <span class="pl-c">// local time zone. Which you might know. But you might not.</span>
    <span class="pl-k">let</span> got<span class="pl-kos">:</span> <span class="pl-smi">DateTime</span><span class="pl-kos">&lt;</span><span class="pl-smi">Local</span><span class="pl-kos">&gt;</span> = serde_json<span class="pl-kos">::</span><span class="pl-en">from_str</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>json<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>got<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 01:59:59 -05:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> next = got<span class="pl-kos">.</span><span class="pl-en">checked_add_signed</span><span class="pl-kos">(</span><span class="pl-smi">TimeDelta</span><span class="pl-kos">::</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"arithmetic failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>next<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 03:00:59 -04:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Or, if you have a <code>Tz</code> from <code>chrono-tz</code>. But in this case, since <code>chrono-tz</code>
doesn't support Serde, you have to convert to a <code>DateTime&lt;FixedOffset&gt;</code>. Like
above, you'll lose DST safe arithmetic after deserialization:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::{DateTime, FixedOffset, TimeDelta, TimeZone};
use chrono_tz::America::New_York;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = New_York.with_ymd_and_hms(2024, 3, 10, 1, 59, 59)
        .single()
        .context(&quot;invalid naive time&quot;)?;

    let json = serde_json::to_string_pretty(&amp;zdt.fixed_offset())?;
    // Chrono only serializes the offset, which makes lossless
    // deserialization impossible. Chrono loses the time zone
    // information.
    assert_eq!(json, &quot;\&quot;2024-03-10T01:59:59-05:00\&quot;&quot;);

    // The serialized datetime has no time zone information,
    // so unless there is some out-of-band information saying
    // what its time zone is, we're forced to use a fixed offset:
    let got: DateTime&lt;FixedOffset&gt; = serde_json::from_str(&amp;json)?;
    assert_eq!(got.to_string(), &quot;2024-03-10 01:59:59 -05:00&quot;);
    let next = got.checked_add_signed(TimeDelta::minutes(1))
        .context(&quot;arithmetic failed&quot;)?;
    // This is correct for fixed offset, but it's no longer
    // DST aware.
    assert_eq!(next.to_string(), &quot;2024-03-10 02:00:59 -05:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">DateTime</span><span class="pl-kos">,</span> <span class="pl-v">FixedOffset</span><span class="pl-kos">,</span> <span class="pl-v">TimeDelta</span><span class="pl-kos">,</span> <span class="pl-v">TimeZone</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono_tz<span class="pl-kos">::</span><span class="pl-smi">America</span><span class="pl-kos">::</span><span class="pl-v">New_York</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-v">New_York</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">single</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid naive time"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> json = serde_json<span class="pl-kos">::</span><span class="pl-en">to_string_pretty</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt<span class="pl-kos">.</span><span class="pl-en">fixed_offset</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// Chrono only serializes the offset, which makes lossless</span>
    <span class="pl-c">// deserialization impossible. Chrono loses the time zone</span>
    <span class="pl-c">// information.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>json<span class="pl-kos">,</span> <span class="pl-s">"<span class="pl-cce">\"</span>2024-03-10T01:59:59-05:00<span class="pl-cce">\"</span>"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// The serialized datetime has no time zone information,</span>
    <span class="pl-c">// so unless there is some out-of-band information saying</span>
    <span class="pl-c">// what its time zone is, we're forced to use a fixed offset:</span>
    <span class="pl-k">let</span> got<span class="pl-kos">:</span> <span class="pl-smi">DateTime</span><span class="pl-kos">&lt;</span><span class="pl-smi">FixedOffset</span><span class="pl-kos">&gt;</span> = serde_json<span class="pl-kos">::</span><span class="pl-en">from_str</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>json<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>got<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 01:59:59 -05:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> next = got<span class="pl-kos">.</span><span class="pl-en">checked_add_signed</span><span class="pl-kos">(</span><span class="pl-smi">TimeDelta</span><span class="pl-kos">::</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"arithmetic failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// This is correct for fixed offset, but it's no longer</span>
    <span class="pl-c">// DST aware.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>next<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 02:00:59 -05:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The main way to solve this problem (and is how <code>java.time</code>, Temporal and Jiff
solve it), is by supporting <a href="https://datatracker.ietf.org/doc/rfc9557/" rel="nofollow">RFC 9557</a>. Otherwise, the only way to fully
capture Jiff's functionality in Chrono is to define a custom serialization
format that includes the instant, the time zone identifier <em>and</em> the offset.
(The offset is used for conflict resolution when deserializing datetimes made
in the future for which their offset has changed due to changes in the time
zone database.)</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff provides support for zone aware calendar arithmetic</h3><a id="user-content-jiff-provides-support-for-zone-aware-calendar-arithmetic" class="anchor" aria-label="Permalink: Jiff provides support for zone aware calendar arithmetic" href="#jiff-provides-support-for-zone-aware-calendar-arithmetic"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">With Jiff, you can add non-uniform units like days to time zone aware datetimes,
and get non-uniform units like days as a representation of a span between
datetimes. And they agree on the results.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, ToSpan, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = zdt1.checked_add(1.day())?;

    // Even though 2 o'clock didn't occur on 2024-03-10, adding 1 day
    // returns the same civil time the next day.
    assert_eq!(zdt2.to_string(), &quot;2024-03-10T21:00:00-04:00[America/New_York]&quot;);
    // The span of time is 23 hours:
    assert_eq!(&amp;zdt2 - &amp;zdt1, 23.hours().fieldwise());
    // But if you ask for the span in units of days, you get exactly 1:
    assert_eq!(zdt1.until((Unit::Day, &amp;zdt2))?, 1.day().fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">9</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">21</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">day</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-c">// Even though 2 o'clock didn't occur on 2024-03-10, adding 1 day</span>
    <span class="pl-c">// returns the same civil time the next day.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10T21:00:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// The span of time is 23 hours:</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt2 - <span class="pl-c1">&amp;</span>zdt1<span class="pl-kos">,</span> <span class="pl-c1">23</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// But if you ask for the span in units of days, you get exactly 1:</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt1<span class="pl-kos">.</span>until<span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-v">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">,</span> <span class="pl-c1">&amp;</span>zdt2<span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">.</span>day<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">This is important and difficult to get right because some days are only 23
hours long (typically the day of the year where DST starts) and some days are
25 hours long (typically the day of the year where DST ends). With Jiff, you
can seamlessly go back-and-forth between calendar units and clock units without
worrying about whether "day" will be interpreted differently.</p>
<p dir="auto">Chrono has some support for this. Namely, it can add units of days in a time
zone aware fashion, but it cannot produce spans of time involving days between
two zone aware datetimes that is consistent with adding days.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::{Days, TimeDelta, TimeZone};
use chrono_tz::America::New_York;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = New_York.with_ymd_and_hms(2024, 3, 9, 21, 0, 0)
        .single()
        .context(&quot;invalid naive time&quot;)?;

    // Adding 1 day via TimeDelta leads to a result that is
    // 24 hours later, including the gap at 2am on 2024-03-10.
    // As a result, you get a different civil time, which is
    // usually not what is intended.
    let zdt2 = zdt1.checked_add_signed(TimeDelta::days(1))
        .context(&quot;adding a time delta failed&quot;)?;
    assert_eq!(zdt2.to_string(), &quot;2024-03-10 22:00:00 EDT&quot;);

    // However, Chrono does expose a separate API for adding
    // units of days specifically. This does get you the
    // correct result.
    let zdt2 = zdt1.checked_add_days(Days::new(1))
        .context(&quot;adding days failed&quot;)?;
    assert_eq!(zdt2.to_string(), &quot;2024-03-10 21:00:00 EDT&quot;);

    // The only way to compute a duration between two datetimes
    // in Chrono is with a `TimeDelta`:
    let delta = zdt2.signed_duration_since(&amp;zdt1);
    // And since `TimeDelta` assumes all days are exactly 24
    // hours long, you get a result of `0` days. If this were
    // a fold, the number of days would be `1`, but you'd also
    // have a number of hours equal to `1`.
    assert_eq!(delta.num_days(), 0);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Days</span><span class="pl-kos">,</span> <span class="pl-v">TimeDelta</span><span class="pl-kos">,</span> <span class="pl-v">TimeZone</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono_tz<span class="pl-kos">::</span><span class="pl-smi">America</span><span class="pl-kos">::</span><span class="pl-v">New_York</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-v">New_York</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">9</span><span class="pl-kos">,</span> <span class="pl-c1">21</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">single</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid naive time"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-c">// Adding 1 day via TimeDelta leads to a result that is</span>
    <span class="pl-c">// 24 hours later, including the gap at 2am on 2024-03-10.</span>
    <span class="pl-c">// As a result, you get a different civil time, which is</span>
    <span class="pl-c">// usually not what is intended.</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">checked_add_signed</span><span class="pl-kos">(</span><span class="pl-smi">TimeDelta</span><span class="pl-kos">::</span><span class="pl-en">days</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"adding a time delta failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 22:00:00 EDT"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// However, Chrono does expose a separate API for adding</span>
    <span class="pl-c">// units of days specifically. This does get you the</span>
    <span class="pl-c">// correct result.</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">checked_add_days</span><span class="pl-kos">(</span><span class="pl-smi">Days</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"adding days failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 21:00:00 EDT"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// The only way to compute a duration between two datetimes</span>
    <span class="pl-c">// in Chrono is with a `TimeDelta`:</span>
    <span class="pl-k">let</span> delta = zdt2<span class="pl-kos">.</span><span class="pl-en">signed_duration_since</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt1<span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// And since `TimeDelta` assumes all days are exactly 24</span>
    <span class="pl-c">// hours long, you get a result of `0` days. If this were</span>
    <span class="pl-c">// a fold, the number of days would be `1`, but you'd also</span>
    <span class="pl-c">// have a number of hours equal to `1`.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>delta<span class="pl-kos">.</span>num_days<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff losslessly roundtrips durations</h3><a id="user-content-jiff-losslessly-roundtrips-durations" class="anchor" aria-label="Permalink: Jiff losslessly roundtrips durations" href="#jiff-losslessly-roundtrips-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Jiff implements something close to ISO 8601 to provide lossless serialization
and deserialization of its <code>Span</code> type. A <code>Span</code> covers both calendar and clock
units.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{Span, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let span = 5.years().months(2).days(1).hours(20);
    let json = serde_json::to_string_pretty(&amp;span)?;
    assert_eq!(json, &quot;\&quot;P5Y2M1DT20H\&quot;&quot;);

    let got: Span = serde_json::from_str(&amp;json)?;
    assert_eq!(got, span.fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Span</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> span = <span class="pl-c1">5</span><span class="pl-kos">.</span><span class="pl-en">years</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">months</span><span class="pl-kos">(</span><span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">days</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-c1">20</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> json = serde_json<span class="pl-kos">::</span><span class="pl-en">to_string_pretty</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>span<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>json<span class="pl-kos">,</span> <span class="pl-s">"<span class="pl-cce">\"</span>P5Y2M1DT20H<span class="pl-cce">\"</span>"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> got<span class="pl-kos">:</span> <span class="pl-smi">Span</span> = serde_json<span class="pl-kos">::</span><span class="pl-en">from_str</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>json<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>got<span class="pl-kos">,</span> span<span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Chrono <a href="https://github.com/chronotope/chrono/issues/117" data-hovercard-type="issue" data-hovercard-url="/chronotope/chrono/issues/117/hovercard">does not currently have Serde support for its duration type</a>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports dealing with gaps in civil time</h3><a id="user-content-jiff-supports-dealing-with-gaps-in-civil-time" class="anchor" aria-label="Permalink: Jiff supports dealing with gaps in civil time" href="#jiff-supports-dealing-with-gaps-in-civil-time"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">A gap in civil time most typically occurs when a particular region enters
daylight saving time. When this happens, some time on the clocks in that region
is skipped. It never appears. (A fold happens when the clocks are rolled back,
usually when leaving daylight saving time. In this case, some time on the clock
is repeated.)</p>
<p dir="auto">Jiff supports automatically selecting a "reasonable" choice in either case
via its "compatible" strategy (as specified by <a href="https://datatracker.ietf.org/doc/html/rfc5545" rel="nofollow">RFC 5545</a>).</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::Zoned;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // This is a gap. The default strategy takes the time after the gap.
    let zdt: Zoned = &quot;2024-03-10 02:30[America/New_York]&quot;.parse()?;
    assert_eq!(zdt.to_string(), &quot;2024-03-10T03:30:00-04:00[America/New_York]&quot;);

    // This is a fold. The default strategy takes the time before the fold.
    let zdt: Zoned = &quot;2024-11-03 01:30[America/New_York]&quot;.parse()?;
    // The time after the fold would be identical,
    // except the offset would be -05.
    assert_eq!(zdt.to_string(), &quot;2024-11-03T01:30:00-04:00[America/New_York]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-v">Zoned</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// This is a gap. The default strategy takes the time after the gap.</span>
    <span class="pl-k">let</span> zdt<span class="pl-kos">:</span> <span class="pl-smi">Zoned</span> = <span class="pl-s">"2024-03-10 02:30[America/New_York]"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10T03:30:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// This is a fold. The default strategy takes the time before the fold.</span>
    <span class="pl-k">let</span> zdt<span class="pl-kos">:</span> <span class="pl-smi">Zoned</span> = <span class="pl-s">"2024-11-03 01:30[America/New_York]"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// The time after the fold would be identical,</span>
    <span class="pl-c">// except the offset would be -05.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-11-03T01:30:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Jiff also exposes all information available with respect to ambiguous civil
datetimes via <code>tz::AmbiguousZoned</code>, <code>tz::AmbiguousTimestamp</code> and
<code>tz::AmbiguousOffset</code>. This enables callers to implement whatever strategy
they want.</p>
<p dir="auto">While Chrono will let you deal with folds, it returns <code>MappedLocalTime::None</code>
in the case of a gap with no additional information. So there's really nothing
else you can conveniently do in this case except return an error:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use chrono::{offset::MappedLocalTime, TimeZone};
use chrono_tz::America::New_York;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // For gaps, Chrono exposes no additional information.
    let mapped = New_York.with_ymd_and_hms(2024, 3, 10, 2, 30, 0);
    assert_eq!(mapped, MappedLocalTime::None);

    // For folds, Chrono gives you the two choices.
    // This is approximately equivalent to what Jiff exposes
    // in the case of a fold.
    let zdt = New_York.with_ymd_and_hms(2024, 11, 3, 1, 30, 0)
        .earliest()
        .context(&quot;invalid datetime&quot;)?;
    assert_eq!(zdt.to_string(), &quot;2024-11-03 01:30:00 EDT&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono<span class="pl-kos">::</span><span class="pl-kos">{</span>offset<span class="pl-kos">::</span><span class="pl-v">MappedLocalTime</span><span class="pl-kos">,</span> <span class="pl-v">TimeZone</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> chrono_tz<span class="pl-kos">::</span><span class="pl-smi">America</span><span class="pl-kos">::</span><span class="pl-v">New_York</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// For gaps, Chrono exposes no additional information.</span>
    <span class="pl-k">let</span> mapped = <span class="pl-v">New_York</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>mapped<span class="pl-kos">,</span> <span class="pl-v">MappedLocalTime</span><span class="pl-kos">::</span><span class="pl-v">None</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// For folds, Chrono gives you the two choices.</span>
    <span class="pl-c">// This is approximately equivalent to what Jiff exposes</span>
    <span class="pl-c">// in the case of a fold.</span>
    <span class="pl-k">let</span> zdt = <span class="pl-v">New_York</span><span class="pl-kos">.</span><span class="pl-en">with_ymd_and_hms</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">earliest</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"invalid datetime"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-11-03 01:30:00 EDT"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports rounding durations</h3><a id="user-content-jiff-supports-rounding-durations" class="anchor" aria-label="Permalink: Jiff supports rounding durations" href="#jiff-supports-rounding-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">In Jiff, one can round the duration computed between two datetimes:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(&quot;America/New_York&quot;)?;

    let round_options = ZonedDifference::new(&amp;zdt2)
        .largest(Unit::Year)
        .smallest(Unit::Day)
        .mode(RoundMode::HalfExpand);
    let span = zdt1.until(round_options)?;
    assert_eq!(span.fieldwise(), 22.years().months(7).days(24));

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">RoundMode</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">,</span> <span class="pl-v">ZonedDifference</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2001</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">18</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">8</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">22</span><span class="pl-kos">,</span> <span class="pl-c1">38</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> round_options = <span class="pl-smi">ZonedDifference</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt2<span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Year</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">smallest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">mode</span><span class="pl-kos">(</span><span class="pl-smi">RoundMode</span><span class="pl-kos">::</span><span class="pl-v">HalfExpand</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span = zdt1<span class="pl-kos">.</span><span class="pl-en">until</span><span class="pl-kos">(</span>round_options<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">22</span><span class="pl-kos">.</span>years<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>months<span class="pl-kos">(</span><span class="pl-c1">7</span><span class="pl-kos">)</span><span class="pl-kos">.</span>days<span class="pl-kos">(</span><span class="pl-c1">24</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">While Chrono supports rounding datetimes themselves via its
<code>chrono::duration::DurationRound</code> trait, it does not support rounding durations
themselves. Indeed, its principle duration type, <code>TimeDelta</code>, is an "absolute"
duration like <code>std::time::Duration</code> (except that it is signed). It doesn't keep
track of individual units like Jiff does. Instead, everything gets normalized
into a 96-bit integer number of nanoseconds. With this representation, it is
impossible to do DST safe rounding to non-uniform units like days.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports zone-aware rounding of durations</h3><a id="user-content-jiff-supports-zone-aware-rounding-of-durations" class="anchor" aria-label="Permalink: Jiff supports zone-aware rounding of durations" href="#jiff-supports-zone-aware-rounding-of-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Jiff's duration rounding is time zone aware. For example, if you're rounding to
a number of days, it knows to round 11.5 hours up to 1 day on days with gaps,
and round 12 hours down to 0 days on days with folds. The only requirement
is that we provide a reference datetime with which to interpret the span.</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, SpanRound, ToSpan, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let gapday = date(2024, 3, 10).in_tz(&quot;America/New_York&quot;)?;
    let foldday = date(2024, 11, 3).in_tz(&quot;America/New_York&quot;)?;

    let span1 = 11.hours().minutes(30);
    let span2 = span1.round(
        SpanRound::new().smallest(Unit::Day).relative(&amp;gapday),
    )?;
    // rounds up, even though on a normal day 11.5 hours would round down.
    assert_eq!(span2, 1.day().fieldwise());

    let span1 = 12.hours();
    let span2 = span1.round(
        SpanRound::new().smallest(Unit::Day).relative(&amp;foldday),
    )?;
    // rounds down, even though on a normal day 12 hours would round up.
    assert_eq!(span2, 0.days().fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">SpanRound</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> gapday = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> foldday = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> span1 = <span class="pl-c1">11</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-c1">30</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span>
        <span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">smallest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">relative</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>gapday<span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// rounds up, even though on a normal day 11.5 hours would round down.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">.</span>day<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> span1 = <span class="pl-c1">12</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span>
        <span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">smallest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">relative</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>foldday<span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// rounds down, even though on a normal day 12 hours would round up.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">.</span>days<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">As with the previous section, Chrono does not support rounding durations or
rounding units like <code>Days</code> with respect to a reference datetime.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports re-balancing durations</h3><a id="user-content-jiff-supports-re-balancing-durations" class="anchor" aria-label="Permalink: Jiff supports re-balancing durations" href="#jiff-supports-re-balancing-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">This example is like the one above, except we choose a smaller "largest" unit:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(&quot;America/New_York&quot;)?;

    let round_options = ZonedDifference::new(&amp;zdt2)
        .largest(Unit::Month)
        .smallest(Unit::Day)
        .mode(RoundMode::HalfExpand);
    let span = zdt1.until(round_options)?;
    assert_eq!(span, 271.months().days(24).fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">RoundMode</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">,</span> <span class="pl-v">ZonedDifference</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2001</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">18</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">8</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">22</span><span class="pl-kos">,</span> <span class="pl-c1">38</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> round_options = <span class="pl-smi">ZonedDifference</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt2<span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Month</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">smallest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">mode</span><span class="pl-kos">(</span><span class="pl-smi">RoundMode</span><span class="pl-kos">::</span><span class="pl-v">HalfExpand</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span = zdt1<span class="pl-kos">.</span><span class="pl-en">until</span><span class="pl-kos">(</span>round_options<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">,</span> <span class="pl-c1">271</span><span class="pl-kos">.</span>months<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>days<span class="pl-kos">(</span><span class="pl-c1">24</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports getting the <code>nth</code> weekday from the current date</h3><a id="user-content-jiff-supports-getting-the-nth-weekday-from-the-current-date" class="anchor" aria-label="Permalink: Jiff supports getting the nth weekday from the current date" href="#jiff-supports-getting-the-nth-weekday-from-the-current-date"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::civil::{date, Weekday};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = date(2024, 7, 11).at(22, 59, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    assert_eq!(zdt.weekday(), Weekday::Thursday);

    let next_tuesday = zdt.nth_weekday(1, Weekday::Tuesday)?;
    assert_eq!(
        next_tuesday.to_string(),
        &quot;2024-07-16T22:59:00-04:00[America/New_York]&quot;,
    );

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span>civil<span class="pl-kos">::</span><span class="pl-kos">{</span>date<span class="pl-kos">,</span> <span class="pl-v">Weekday</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">22</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>weekday<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-v">Weekday</span><span class="pl-kos">::</span><span class="pl-v">Thursday</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> next_tuesday = zdt<span class="pl-kos">.</span><span class="pl-en">nth_weekday</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-smi">Weekday</span><span class="pl-kos">::</span><span class="pl-v">Tuesday</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>
        next_tuesday<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
        <span class="pl-s">"2024-07-16T22:59:00-04:00[America/New_York]"</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Chrono does have <code>NaiveDate::from_weekday_of_month_opt</code>, but it only counts
the number of weekdays for a particular month. (The Jiff equivalent is
<code>nth_weekday_of_month</code>.) Moreover, Chrono's method is only available on naive
dates and not zone aware datetimes.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports detecting time zone offset conflicts</h3><a id="user-content-jiff-supports-detecting-time-zone-offset-conflicts" class="anchor" aria-label="Permalink: Jiff supports detecting time zone offset conflicts" href="#jiff-supports-detecting-time-zone-offset-conflicts"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">One of the problems with storing datetimes in the future is that time
zone rules can change. For example, if you stored the zone aware datetime
<code>2020-01-15T12:00-02[America/Sao_Paulo]</code> in 2018, then it would be considered
to be in daylight saving time with an offset of <code>-2</code>. However, in 2019,
daylight saving time was abolished in this time zone, which renders the
datetime invalid because its offset <em>should</em> be <code>-3</code>.</p>
<p dir="auto">Jiff can detect these sorts of conflicts and will actually return a parse error
by default. We exemplify this by creating and serializing a zoned datetime from
an old copy of the Time Zone Database, and then try to parse it back using our
system's current copy of the Time Zone Database. (This also demonstrate's Jiff
support for using multiple copies of the Time Zone Database simultaneously.
But the main point here is to simulate the process of "serialize datetime,
time zone rules change, deserialize datetime.")</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{fmt::temporal::DateTimeParser, tz::{self, TimeZoneDatabase}};

// We use a custom parser with a default configuration because we need
// to ask the parser to use a different time zone database than the
// default. This can't be done via the nice `&quot;...&quot;.parse()` API one
// would typically use.
static PARSER: DateTimeParser = DateTimeParser::new();

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // Open a version of tzdb from before Brazil announced its abolition
    // of daylight saving time.
    let tzdb2018 = TimeZoneDatabase::from_dir(&quot;path/to/tzdb-2018b&quot;)?;
    // Open the system tzdb.
    let tzdb = tz::db();

    // Parse the same datetime string with the same parser, but using two
    // different versions of tzdb.
    let dt = &quot;2020-01-15T12:00[America/Sao_Paulo]&quot;;
    let zdt2018 = PARSER.parse_zoned_with(&amp;tzdb2018, dt)?;
    let zdt = PARSER.parse_zoned_with(tzdb, dt)?;

    // Before DST was abolished, 2020-01-15 was in DST, which corresponded
    // to UTC offset -02. Since DST rules applied to datetimes in the
    // future, the 2018 version of tzdb would lead one to interpret
    // 2020-01-15 as being in DST.
    assert_eq!(zdt2018.offset(), tz::offset(-2));
    // But DST was abolished in 2019, which means that 2020-01-15 was no
    // no longer in DST. So after a tzdb update, the same datetime as above
    // now has a different offset.
    assert_eq!(zdt.offset(), tz::offset(-3));

    // So if you try to parse a datetime serialized from an older copy of
    // tzdb with a new copy of tzdb, you'll get an error under the default
    // configuration because of `OffsetConflict::Reject`. This would succeed if
    // you parsed it using tzdb2018!
    assert!(PARSER.parse_zoned_with(tzdb, zdt2018.to_string()).is_err());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>fmt<span class="pl-kos">::</span>temporal<span class="pl-kos">::</span><span class="pl-v">DateTimeParser</span><span class="pl-kos">,</span> tz<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-smi">self</span><span class="pl-kos">,</span> <span class="pl-v">TimeZoneDatabase</span><span class="pl-kos">}</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-c">// We use a custom parser with a default configuration because we need</span>
<span class="pl-c">// to ask the parser to use a different time zone database than the</span>
<span class="pl-c">// default. This can't be done via the nice `"...".parse()` API one</span>
<span class="pl-c">// would typically use.</span>
<span class="pl-k">static</span> <span class="pl-v">PARSER</span><span class="pl-kos">:</span> <span class="pl-smi">DateTimeParser</span> = <span class="pl-smi">DateTimeParser</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Open a version of tzdb from before Brazil announced its abolition</span>
    <span class="pl-c">// of daylight saving time.</span>
    <span class="pl-k">let</span> tzdb2018 = <span class="pl-smi">TimeZoneDatabase</span><span class="pl-kos">::</span><span class="pl-en">from_dir</span><span class="pl-kos">(</span><span class="pl-s">"path/to/tzdb-2018b"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// Open the system tzdb.</span>
    <span class="pl-k">let</span> tzdb = tz<span class="pl-kos">::</span><span class="pl-en">db</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// Parse the same datetime string with the same parser, but using two</span>
    <span class="pl-c">// different versions of tzdb.</span>
    <span class="pl-k">let</span> dt = <span class="pl-s">"2020-01-15T12:00[America/Sao_Paulo]"</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2018 = <span class="pl-v">PARSER</span><span class="pl-kos">.</span><span class="pl-en">parse_zoned_with</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>tzdb2018<span class="pl-kos">,</span> dt<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt = <span class="pl-v">PARSER</span><span class="pl-kos">.</span><span class="pl-en">parse_zoned_with</span><span class="pl-kos">(</span>tzdb<span class="pl-kos">,</span> dt<span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-c">// Before DST was abolished, 2020-01-15 was in DST, which corresponded</span>
    <span class="pl-c">// to UTC offset -02. Since DST rules applied to datetimes in the</span>
    <span class="pl-c">// future, the 2018 version of tzdb would lead one to interpret</span>
    <span class="pl-c">// 2020-01-15 as being in DST.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2018<span class="pl-kos">.</span>offset<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> tz<span class="pl-kos">::</span>offset<span class="pl-kos">(</span>-<span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c">// But DST was abolished in 2019, which means that 2020-01-15 was no</span>
    <span class="pl-c">// no longer in DST. So after a tzdb update, the same datetime as above</span>
    <span class="pl-c">// now has a different offset.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>offset<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> tz<span class="pl-kos">::</span>offset<span class="pl-kos">(</span>-<span class="pl-c1">3</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// So if you try to parse a datetime serialized from an older copy of</span>
    <span class="pl-c">// tzdb with a new copy of tzdb, you'll get an error under the default</span>
    <span class="pl-c">// configuration because of `OffsetConflict::Reject`. This would succeed if</span>
    <span class="pl-c">// you parsed it using tzdb2018!</span>
    <span class="pl-en">assert</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-v">PARSER</span><span class="pl-kos">.</span>parse_zoned_with<span class="pl-kos">(</span>tzdb<span class="pl-kos">,</span> zdt2018<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span>is_err<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">With Chrono, this sort of checking isn't possible in the first place because
it doesn't support an interchange format that includes the IANA time zone
identifier.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports adding durations with calendar units</h3><a id="user-content-jiff-supports-adding-durations-with-calendar-units" class="anchor" aria-label="Permalink: Jiff supports adding durations with calendar units" href="#jiff-supports-adding-durations-with-calendar-units"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Since <code>Span</code> is Jiff's single duration type that combines calendar and clock
units, one can freely add them together. The only requirement is that if a span
has calendar units, you need to provide a reference date. (Because 1 month from
April 1 is shorter than 1 month from May 1.)</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let span1 = 2.years().months(4).days(25).hours(23);
    let span2 = 3.hours();
    let span3 = span1.checked_add((span2, date(2024, 1, 1)))?;
    assert_eq!(span3.fieldwise(), 2.years().months(4).days(26).hours(2));

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">2</span><span class="pl-kos">.</span><span class="pl-en">years</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">months</span><span class="pl-kos">(</span><span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">days</span><span class="pl-kos">(</span><span class="pl-c1">25</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-c1">23</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = <span class="pl-c1">3</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span3 = span1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span3<span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">.</span>years<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>months<span class="pl-kos">(</span><span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">.</span>days<span class="pl-kos">(</span><span class="pl-c1">26</span><span class="pl-kos">)</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">While Chrono has types like <code>Months</code> and <code>Days</code>, there's no way to combine
them into one, and Chrono does not provide operations on both at the same time.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports zone-aware re-balancing of durations</h3><a id="user-content-jiff-supports-zone-aware-re-balancing-of-durations" class="anchor" aria-label="Permalink: Jiff supports zone-aware re-balancing of durations" href="#jiff-supports-zone-aware-re-balancing-of-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">If you have a span of <code>1.day()</code> and want to convert it to hours, then that
calculation depends on how long the day is. If you provide a civil date as
a relative reference point, then Jiff assumes the day is always 24 hours long:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil, SpanRound, ToSpan, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let relative = civil::date(2024, 4, 1);
    let span1 = 1.day();
    let span2 = span1.round(
        SpanRound::new().largest(Unit::Hour).relative(relative),
    )?;
    assert_eq!(span2, 24.hours().fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">,</span> <span class="pl-v">SpanRound</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> relative = civil<span class="pl-kos">::</span><span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">day</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span>
        <span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">relative</span><span class="pl-kos">(</span>relative<span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">24</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">But if a reference date is provided with a time zone, then the re-balancing is
DST safe:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, SpanRound, ToSpan, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // In the case of a gap (typically transitioning in DST):
    let zdt = date(2024, 3, 9).at(21, 0, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let span1 = 1.day();
    let span2 = span1.round(
        SpanRound::new().largest(Unit::Hour).relative(&amp;zdt)
    )?;
    assert_eq!(span2, 23.hours().fieldwise());

    // In the case of a fold (typically transitioning out of DST):
    let zdt = date(2024, 11, 2).at(21, 0, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let span1 = 1.day();
    let span2 = span1.round(
        SpanRound::new().largest(Unit::Hour).relative(&amp;zdt)
    )?;
    assert_eq!(span2, 25.hours().fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">SpanRound</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// In the case of a gap (typically transitioning in DST):</span>
    <span class="pl-k">let</span> zdt = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">9</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">21</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">day</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span>
        <span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">relative</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt<span class="pl-kos">)</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">23</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// In the case of a fold (typically transitioning out of DST):</span>
    <span class="pl-k">let</span> zdt = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">2</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">21</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">day</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span>
        <span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">relative</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt<span class="pl-kos">)</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">25</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff is generally faster than Chrono</h3><a id="user-content-jiff-is-generally-faster-than-chrono" class="anchor" aria-label="Permalink: Jiff is generally faster than Chrono" href="#jiff-is-generally-faster-than-chrono"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">There are some cases where Chrono is faster than Jiff, but Jiff should
generally be competitive for equivalent operations. It's generally not
possible for Chrono or Jiff to always be faster than the other, since
they each use different representations for fundamental types. This in turn
makes some operations faster and others slower, depending on what you're
trying to do. With that said, Jiff is uniformly faster than Chrono when it
comes to printing and parsing.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ cd bench
$ cargo bench -- --save-baseline base
[.. snip ..]
$ critcmp base -g '(.*)/(?:jiff|chrono)$'
group                                                           baseline//chrono                       baseline//jiff
-----                                                           ----------------                       --------------
civil_datetime/add_days/diffyear/duration                       1.00      8.5±0.08ns        ? ?/sec    1.56     13.3±0.15ns        ? ?/sec
civil_datetime/add_days/diffyear/span                                                                  1.00     23.9±0.13ns        ? ?/sec
civil_datetime/add_days/sameyear/duration                       1.00      6.8±0.05ns        ? ?/sec    1.96     13.3±0.17ns        ? ?/sec
civil_datetime/add_days/sameyear/span                                                                  1.00     23.8±0.13ns        ? ?/sec
civil_datetime/to_timestamp_static/bundled                      2.05     22.3±0.24ns        ? ?/sec    1.00     10.9±0.14ns        ? ?/sec
civil_datetime/to_timestamp_static/zoneinfo                     1.53     16.2±0.15ns        ? ?/sec    1.00     10.6±0.09ns        ? ?/sec
civil_datetime/to_timestamp_tzdb_lookup/bundled                 1.00     32.0±0.15ns        ? ?/sec
civil_datetime/to_timestamp_tzdb_lookup/zoneinfo                45.85  1919.7±6.17ns        ? ?/sec    1.00     41.9±0.15ns        ? ?/sec
date/add_days/diffyear/duration                                 1.00      5.8±0.05ns        ? ?/sec    1.12      6.5±0.04ns        ? ?/sec
date/add_days/diffyear/span                                                                            1.00      6.5±0.04ns        ? ?/sec
date/add_days/one/duration                                      1.00      2.1±0.02ns        ? ?/sec    2.55      5.4±0.05ns        ? ?/sec
date/add_days/one/span                                                                                 1.00      5.8±0.02ns        ? ?/sec
date/add_days/sameyear/duration                                 1.00      2.1±0.01ns        ? ?/sec    3.08      6.5±0.05ns        ? ?/sec
date/add_days/sameyear/span                                                                            1.00      6.5±0.05ns        ? ?/sec
date/difference_days/duration                                   1.18      3.4±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec
date/difference_days/span                                                                              1.00      2.5±0.02ns        ? ?/sec
date/tomorrow/diff-month                                        1.00      0.4±0.00ns        ? ?/sec    3.25      1.3±0.01ns        ? ?/sec
date/tomorrow/diff-year                                         1.16      1.7±0.01ns        ? ?/sec    1.00      1.4±0.01ns        ? ?/sec
date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec    1.99      0.8±0.00ns        ? ?/sec
date/yesterday/diff-month                                       1.00      0.4±0.02ns        ? ?/sec    3.17      1.3±0.01ns        ? ?/sec
date/yesterday/diff-year                                        1.85      2.0±0.01ns        ? ?/sec    1.00      1.1±0.01ns        ? ?/sec
date/yesterday/same-month                                       1.00      0.4±0.03ns        ? ?/sec    1.72      0.7±0.02ns        ? ?/sec
parse/civil_datetime                                            2.95     73.6±0.72ns        ? ?/sec    1.00     24.9±0.19ns        ? ?/sec
parse/rfc2822                                                   3.09     59.9±0.30ns        ? ?/sec    1.00     19.3±0.17ns        ? ?/sec
parse/strptime/oneshot                                          3.11    197.8±0.80ns        ? ?/sec    1.00     63.6±1.19ns        ? ?/sec
parse/strptime/prebuilt                                         1.00     77.1±1.44ns        ? ?/sec
print/civil_datetime                                            13.10   147.4±0.60ns        ? ?/sec    1.00     11.3±0.04ns        ? ?/sec
print/iso8601_duration/long-time/duration/buffer                2.38     46.5±0.34ns        ? ?/sec    1.00     19.5±0.04ns        ? ?/sec
print/iso8601_duration/long-time/duration/to_string             3.13     71.7±0.36ns        ? ?/sec    1.00     23.0±0.07ns        ? ?/sec
print/iso8601_duration/short/duration/buffer                    2.65     32.3±0.30ns        ? ?/sec    1.00     12.2±0.04ns        ? ?/sec
print/iso8601_duration/short/duration/to_string                 2.08     36.8±0.33ns        ? ?/sec    1.00     17.7±0.05ns        ? ?/sec
print/iso8601_duration/tiny/duration/buffer                     2.74     31.6±0.32ns        ? ?/sec    1.00     11.6±0.03ns        ? ?/sec
print/iso8601_duration/tiny/duration/to_string                  2.28     36.5±0.40ns        ? ?/sec    1.00     16.0±0.08ns        ? ?/sec
print/rfc2822/buffer                                            4.91     64.6±0.59ns        ? ?/sec    1.00     13.2±0.03ns        ? ?/sec
print/rfc2822/to_string                                         5.75    111.0±0.37ns        ? ?/sec    1.00     19.3±0.05ns        ? ?/sec
print/rfc3339/buffer                                            3.79     64.2±0.56ns        ? ?/sec    1.00     17.0±0.14ns        ? ?/sec
print/rfc3339/to_string                                         4.75    112.4±0.33ns        ? ?/sec    1.00     23.6±0.11ns        ? ?/sec
print/rfc9557/buffer                                                                                   1.00     16.2±0.05ns        ? ?/sec
print/rfc9557/to_string                                                                                1.00     22.2±0.07ns        ? ?/sec
print/strftime/oneshot/buffer                                   3.90    213.9±1.99ns        ? ?/sec    1.00     54.8±0.32ns        ? ?/sec
print/strftime/oneshot/to_string                                3.63    261.3±1.26ns        ? ?/sec    1.00     72.1±0.49ns        ? ?/sec
print/strftime/oneshot/zoned                                                                           1.00     65.5±0.64ns        ? ?/sec
print/strftime/prebuilt/buffer                                  1.00     85.4±0.52ns        ? ?/sec
print/strftime/prebuilt/to_string                               1.00    147.4±0.76ns        ? ?/sec
timestamp/add_time_secs/duration                                2.42      6.1±0.08ns        ? ?/sec    1.00      2.5±0.03ns        ? ?/sec
timestamp/add_time_secs/span                                                                           1.00      3.8±0.06ns        ? ?/sec
timestamp/add_time_subsec/duration                              2.10      6.1±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec
timestamp/add_time_subsec/span                                                                         1.00      8.1±0.09ns        ? ?/sec
timestamp/every_hour_in_week/byhand                             16.15  1679.6±6.13ns        ? ?/sec    1.00    104.0±0.72ns        ? ?/sec
timestamp/every_hour_in_week/series                                                                    1.00    105.9±0.66ns        ? ?/sec
timestamp/from_seconds/integer                                  14.45     4.7±0.03ns        ? ?/sec    1.00      0.3±0.00ns        ? ?/sec
timestamp/to_civil_datetime_offset_conversion                   1.65      7.3±0.02ns        ? ?/sec    1.00      4.4±0.04ns        ? ?/sec
timestamp/to_civil_datetime_offset_holistic                                                            1.00      4.4±0.04ns        ? ?/sec
timestamp/to_civil_datetime_static/America-New-York/bundled     1.00     16.0±0.16ns        ? ?/sec
timestamp/to_civil_datetime_static/America-New-York/zoneinfo    1.42     18.4±0.11ns        ? ?/sec    1.00     13.0±0.11ns        ? ?/sec
timestamp/to_civil_datetime_static/Asia-Shanghai/bundled        1.00     15.2±0.16ns        ? ?/sec
timestamp/to_civil_datetime_static/Asia-Shanghai/zoneinfo       3.16     15.7±0.11ns        ? ?/sec    1.00      5.0±0.05ns        ? ?/sec
zoned/fixed_offset_add_time/duration                            1.00      6.1±0.06ns        ? ?/sec    1.56      9.5±0.05ns        ? ?/sec
zoned/fixed_offset_add_time/span                                                                       1.00     16.6±0.09ns        ? ?/sec
zoned/fixed_offset_to_civil_datetime                            1.23      5.6±0.01ns        ? ?/sec    1.00      4.5±0.01ns        ? ?/sec
zoned/fixed_offset_to_timestamp                                 3.15      1.2±0.01ns        ? ?/sec    1.00      0.4±0.00ns        ? ?/sec"><pre lang="text" class="notranslate"><code>$ cd bench
$ cargo bench -- --save-baseline base
[.. snip ..]
$ critcmp base -g '(.*)/(?:jiff|chrono)$'
group                                                           baseline//chrono                       baseline//jiff
-----                                                           ----------------                       --------------
civil_datetime/add_days/diffyear/duration                       1.00      8.5±0.08ns        ? ?/sec    1.56     13.3±0.15ns        ? ?/sec
civil_datetime/add_days/diffyear/span                                                                  1.00     23.9±0.13ns        ? ?/sec
civil_datetime/add_days/sameyear/duration                       1.00      6.8±0.05ns        ? ?/sec    1.96     13.3±0.17ns        ? ?/sec
civil_datetime/add_days/sameyear/span                                                                  1.00     23.8±0.13ns        ? ?/sec
civil_datetime/to_timestamp_static/bundled                      2.05     22.3±0.24ns        ? ?/sec    1.00     10.9±0.14ns        ? ?/sec
civil_datetime/to_timestamp_static/zoneinfo                     1.53     16.2±0.15ns        ? ?/sec    1.00     10.6±0.09ns        ? ?/sec
civil_datetime/to_timestamp_tzdb_lookup/bundled                 1.00     32.0±0.15ns        ? ?/sec
civil_datetime/to_timestamp_tzdb_lookup/zoneinfo                45.85  1919.7±6.17ns        ? ?/sec    1.00     41.9±0.15ns        ? ?/sec
date/add_days/diffyear/duration                                 1.00      5.8±0.05ns        ? ?/sec    1.12      6.5±0.04ns        ? ?/sec
date/add_days/diffyear/span                                                                            1.00      6.5±0.04ns        ? ?/sec
date/add_days/one/duration                                      1.00      2.1±0.02ns        ? ?/sec    2.55      5.4±0.05ns        ? ?/sec
date/add_days/one/span                                                                                 1.00      5.8±0.02ns        ? ?/sec
date/add_days/sameyear/duration                                 1.00      2.1±0.01ns        ? ?/sec    3.08      6.5±0.05ns        ? ?/sec
date/add_days/sameyear/span                                                                            1.00      6.5±0.05ns        ? ?/sec
date/difference_days/duration                                   1.18      3.4±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec
date/difference_days/span                                                                              1.00      2.5±0.02ns        ? ?/sec
date/tomorrow/diff-month                                        1.00      0.4±0.00ns        ? ?/sec    3.25      1.3±0.01ns        ? ?/sec
date/tomorrow/diff-year                                         1.16      1.7±0.01ns        ? ?/sec    1.00      1.4±0.01ns        ? ?/sec
date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec    1.99      0.8±0.00ns        ? ?/sec
date/yesterday/diff-month                                       1.00      0.4±0.02ns        ? ?/sec    3.17      1.3±0.01ns        ? ?/sec
date/yesterday/diff-year                                        1.85      2.0±0.01ns        ? ?/sec    1.00      1.1±0.01ns        ? ?/sec
date/yesterday/same-month                                       1.00      0.4±0.03ns        ? ?/sec    1.72      0.7±0.02ns        ? ?/sec
parse/civil_datetime                                            2.95     73.6±0.72ns        ? ?/sec    1.00     24.9±0.19ns        ? ?/sec
parse/rfc2822                                                   3.09     59.9±0.30ns        ? ?/sec    1.00     19.3±0.17ns        ? ?/sec
parse/strptime/oneshot                                          3.11    197.8±0.80ns        ? ?/sec    1.00     63.6±1.19ns        ? ?/sec
parse/strptime/prebuilt                                         1.00     77.1±1.44ns        ? ?/sec
print/civil_datetime                                            13.10   147.4±0.60ns        ? ?/sec    1.00     11.3±0.04ns        ? ?/sec
print/iso8601_duration/long-time/duration/buffer                2.38     46.5±0.34ns        ? ?/sec    1.00     19.5±0.04ns        ? ?/sec
print/iso8601_duration/long-time/duration/to_string             3.13     71.7±0.36ns        ? ?/sec    1.00     23.0±0.07ns        ? ?/sec
print/iso8601_duration/short/duration/buffer                    2.65     32.3±0.30ns        ? ?/sec    1.00     12.2±0.04ns        ? ?/sec
print/iso8601_duration/short/duration/to_string                 2.08     36.8±0.33ns        ? ?/sec    1.00     17.7±0.05ns        ? ?/sec
print/iso8601_duration/tiny/duration/buffer                     2.74     31.6±0.32ns        ? ?/sec    1.00     11.6±0.03ns        ? ?/sec
print/iso8601_duration/tiny/duration/to_string                  2.28     36.5±0.40ns        ? ?/sec    1.00     16.0±0.08ns        ? ?/sec
print/rfc2822/buffer                                            4.91     64.6±0.59ns        ? ?/sec    1.00     13.2±0.03ns        ? ?/sec
print/rfc2822/to_string                                         5.75    111.0±0.37ns        ? ?/sec    1.00     19.3±0.05ns        ? ?/sec
print/rfc3339/buffer                                            3.79     64.2±0.56ns        ? ?/sec    1.00     17.0±0.14ns        ? ?/sec
print/rfc3339/to_string                                         4.75    112.4±0.33ns        ? ?/sec    1.00     23.6±0.11ns        ? ?/sec
print/rfc9557/buffer                                                                                   1.00     16.2±0.05ns        ? ?/sec
print/rfc9557/to_string                                                                                1.00     22.2±0.07ns        ? ?/sec
print/strftime/oneshot/buffer                                   3.90    213.9±1.99ns        ? ?/sec    1.00     54.8±0.32ns        ? ?/sec
print/strftime/oneshot/to_string                                3.63    261.3±1.26ns        ? ?/sec    1.00     72.1±0.49ns        ? ?/sec
print/strftime/oneshot/zoned                                                                           1.00     65.5±0.64ns        ? ?/sec
print/strftime/prebuilt/buffer                                  1.00     85.4±0.52ns        ? ?/sec
print/strftime/prebuilt/to_string                               1.00    147.4±0.76ns        ? ?/sec
timestamp/add_time_secs/duration                                2.42      6.1±0.08ns        ? ?/sec    1.00      2.5±0.03ns        ? ?/sec
timestamp/add_time_secs/span                                                                           1.00      3.8±0.06ns        ? ?/sec
timestamp/add_time_subsec/duration                              2.10      6.1±0.04ns        ? ?/sec    1.00      2.9±0.02ns        ? ?/sec
timestamp/add_time_subsec/span                                                                         1.00      8.1±0.09ns        ? ?/sec
timestamp/every_hour_in_week/byhand                             16.15  1679.6±6.13ns        ? ?/sec    1.00    104.0±0.72ns        ? ?/sec
timestamp/every_hour_in_week/series                                                                    1.00    105.9±0.66ns        ? ?/sec
timestamp/from_seconds/integer                                  14.45     4.7±0.03ns        ? ?/sec    1.00      0.3±0.00ns        ? ?/sec
timestamp/to_civil_datetime_offset_conversion                   1.65      7.3±0.02ns        ? ?/sec    1.00      4.4±0.04ns        ? ?/sec
timestamp/to_civil_datetime_offset_holistic                                                            1.00      4.4±0.04ns        ? ?/sec
timestamp/to_civil_datetime_static/America-New-York/bundled     1.00     16.0±0.16ns        ? ?/sec
timestamp/to_civil_datetime_static/America-New-York/zoneinfo    1.42     18.4±0.11ns        ? ?/sec    1.00     13.0±0.11ns        ? ?/sec
timestamp/to_civil_datetime_static/Asia-Shanghai/bundled        1.00     15.2±0.16ns        ? ?/sec
timestamp/to_civil_datetime_static/Asia-Shanghai/zoneinfo       3.16     15.7±0.11ns        ? ?/sec    1.00      5.0±0.05ns        ? ?/sec
zoned/fixed_offset_add_time/duration                            1.00      6.1±0.06ns        ? ?/sec    1.56      9.5±0.05ns        ? ?/sec
zoned/fixed_offset_add_time/span                                                                       1.00     16.6±0.09ns        ? ?/sec
zoned/fixed_offset_to_civil_datetime                            1.23      5.6±0.01ns        ? ?/sec    1.00      4.5±0.01ns        ? ?/sec
zoned/fixed_offset_to_timestamp                                 3.15      1.2±0.01ns        ? ?/sec    1.00      0.4±0.00ns        ? ?/sec
</code></pre></div>
<p dir="auto">Questions about benchmarks are welcome in
<a href="https://github.com/BurntSushi/jiff/discussions">Discussions on GitHub</a>.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto"><a href="https://docs.rs/time" rel="nofollow"><code>time</code></a> (v0.3.36)</h2><a id="user-content-time-v0336" class="anchor" aria-label="Permalink: time (v0.3.36)" href="#time-v0336"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>time</code> is a Rust datetime library that provides a time zone offset aware
datetime type.</p>
<p dir="auto">For the following comparisons, a <code>Cargo.toml</code> with the following dependencies
should be able to run any of the programs in this section:</p>
<div class="highlight highlight-source-toml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="anyhow = &quot;1.0.81&quot;
jiff = { version = &quot;0.2.0&quot;, features = [&quot;serde&quot;] }
time = { version = &quot;0.3.36&quot;, features = [&quot;local-offset&quot;, &quot;macros&quot;, &quot;parsing&quot;] }
time-tz = &quot;2.0.0&quot;"><pre><span class="pl-smi">anyhow</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.81<span class="pl-pds">"</span></span>
<span class="pl-smi">jiff</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.2.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>serde<span class="pl-pds">"</span></span>] }
<span class="pl-smi">time</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.3.36<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>local-offset<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>macros<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>parsing<span class="pl-pds">"</span></span>] }
<span class="pl-smi">time-tz</span> = <span class="pl-s"><span class="pl-pds">"</span>2.0.0<span class="pl-pds">"</span></span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Time zone database integration</h3><a id="user-content-time-zone-database-integration-1" class="anchor" aria-label="Permalink: Time zone database integration" href="#time-zone-database-integration-1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Like <code>chrono</code>, the <code>time</code> crate does not come with any out of the box
functionality for reading your system's copy of the Time Zone Database.
However, there is a third party crate, <a href="https://docs.rs/time-tz" rel="nofollow"><code>time-tz</code></a>
that provides some time zone support in a fashion similar to <code>chrono-tz</code>. That
is, it requires bundling the time zone data into your binary and does not
support reading the system copy of the Time Zone Database when available.</p>
<p dir="auto">Note also that <code>time</code> does not provide the extension points necessary in its API
to make handling time zone aware datetimes ergonomic. Indeed, many operations
are not expressible at all.</p>
<p dir="auto">The main thing <code>time</code> supports is a concept of "local" time. In particular, it
is limited to determining your system's default time zone offset, but nothing
more. That is, it doesn't support DST safe arithmetic:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use time::{ext::NumericalDuration, macros::datetime, Duration};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // We create a fixed datetime for testing purposes,
    // but it's the same sort of value we would get back
    // from `OffsetDateTime::now_local()`.
    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);
    let dt2 = dt1.checked_add(1.hours())
      .context(&quot;datetime arithmetic failed&quot;)?;
    // The 2 o'clock hour didn't exist on 2024-03-10
    // in New York.
    assert_eq!(dt2.to_string(), &quot;2024-03-10 2:30:00.0 -05:00:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>ext<span class="pl-kos">::</span><span class="pl-v">NumericalDuration</span><span class="pl-kos">,</span> macros<span class="pl-kos">::</span>datetime<span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// We create a fixed datetime for testing purposes,</span>
    <span class="pl-c">// but it's the same sort of value we would get back</span>
    <span class="pl-c">// from `OffsetDateTime::now_local()`.</span>
    <span class="pl-k">let</span> dt1 = <span class="pl-en">datetime</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-c1">2024</span>-<span class="pl-c1">03</span>-<span class="pl-c1">10</span> <span class="pl-c1">01</span><span class="pl-kos">:</span><span class="pl-c1">30</span><span class="pl-kos">:</span><span class="pl-c1">00</span> -<span class="pl-c1">05</span><span class="pl-kos">:</span><span class="pl-c1">00</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> dt2 = dt1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
      <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"datetime arithmetic failed"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-c">// The 2 o'clock hour didn't exist on 2024-03-10</span>
    <span class="pl-c">// in New York.</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>dt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 2:30:00.0 -05:00:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><code>time</code>, in its present design, is fundamentally incapable of doing daylight
saving time safe arithmetic because its <code>OffsetDateTime</code> type doesn't know
anything about the time zone rules. Compare this with Jiff, which lets you not
only create a datetime with an offset, but with a <em>time zone</em>:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2024, 3, 10).at(1, 30, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = zdt1.checked_add(1.hour())?;
    assert_eq!(zdt2.to_string(), &quot;2024-03-10T03:30:00-04:00[America/New_York]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">10</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">hour</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10T03:30:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">If you use <code>time-tz</code>, then you can make the above example with <code>time</code> work:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use anyhow::Context;
use time::{ext::NumericalDuration, macros::datetime, Duration};
use time_tz::{OffsetDateTimeExt, Tz};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let tz = time_tz::timezones::db::america::NEW_YORK;

    // We create a fixed datetime for testing purposes,
    // but it's the same sort of value we would get back
    // from `OffsetDateTime::now_local()`.
    let dt1 = datetime!(2024-03-10 01:30:00 -05:00);
    let dt2 = dt1.checked_add(1.hours())
      .context(&quot;datetime arithmetic failed&quot;)?
      .to_timezone(tz);
    assert_eq!(dt2.to_string(), &quot;2024-03-10 3:30:00.0 -04:00:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> anyhow<span class="pl-kos">::</span><span class="pl-v">Context</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>ext<span class="pl-kos">::</span><span class="pl-v">NumericalDuration</span><span class="pl-kos">,</span> macros<span class="pl-kos">::</span>datetime<span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">use</span> time_tz<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">OffsetDateTimeExt</span><span class="pl-kos">,</span> <span class="pl-v">Tz</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> tz = time_tz<span class="pl-kos">::</span>timezones<span class="pl-kos">::</span>db<span class="pl-kos">::</span>america<span class="pl-kos">::</span><span class="pl-v">NEW_YORK</span><span class="pl-kos">;</span>

    <span class="pl-c">// We create a fixed datetime for testing purposes,</span>
    <span class="pl-c">// but it's the same sort of value we would get back</span>
    <span class="pl-c">// from `OffsetDateTime::now_local()`.</span>
    <span class="pl-k">let</span> dt1 = <span class="pl-en">datetime</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-c1">2024</span>-<span class="pl-c1">03</span>-<span class="pl-c1">10</span> <span class="pl-c1">01</span><span class="pl-kos">:</span><span class="pl-c1">30</span><span class="pl-kos">:</span><span class="pl-c1">00</span> -<span class="pl-c1">05</span><span class="pl-kos">:</span><span class="pl-c1">00</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> dt2 = dt1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
      <span class="pl-kos">.</span><span class="pl-en">context</span><span class="pl-kos">(</span><span class="pl-s">"datetime arithmetic failed"</span><span class="pl-kos">)</span>?
      <span class="pl-kos">.</span><span class="pl-en">to_timezone</span><span class="pl-kos">(</span>tz<span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>dt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-03-10 3:30:00.0 -04:00:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">But note that you have to be careful to call <code>.to_timezone()</code> before printing
the datetime. In particular, there is no time zone aware datetime type.</p>
<p dir="auto">In my comparison with Chrono I went through a lot of examples involving
time zones. I did this because Chrono supports DST safe arithmetic generally,
but with a lot of nuanced differences from what Jiff supports. Conversely,
<code>time</code> doesn't have a time zone aware datetime type. And the time zone support
provided by <code>time-tz</code> is extremely limited. So at this time, in this document,
we won't belabor the point.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>time</code> supports its own custom format description</h3><a id="user-content-time-supports-its-own-custom-format-description" class="anchor" aria-label="Permalink: time supports its own custom format description" href="#time-supports-its-own-custom-format-description"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Some users may find this easier to use:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use time::{macros::format_description, OffsetDateTime};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let format = format_description!(
        &quot;[year]-[month]-[day] [hour]:[minute]:[second] \
         [offset_hour sign:mandatory]:[offset_minute]:[offset_second]&quot;
    );
    let odt = OffsetDateTime::parse(&quot;2024-07-11 22:49:00 -04:00:00&quot;, &amp;format)?;
    assert_eq!(odt.to_string(), &quot;2024-07-11 22:49:00.0 -04:00:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>macros<span class="pl-kos">::</span>format_description<span class="pl-kos">,</span> <span class="pl-v">OffsetDateTime</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> format = <span class="pl-en">format_description</span><span class="pl-en">!</span><span class="pl-kos">(</span>
        <span class="pl-s">"[year]-[month]-[day] [hour]:[minute]:[second] <span class="pl-cce">\</span></span>
<span class="pl-s"><span class="pl-cce"></span>         [offset_hour sign:mandatory]:[offset_minute]:[offset_second]"</span>
    <span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> odt = <span class="pl-smi">OffsetDateTime</span><span class="pl-kos">::</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s">"2024-07-11 22:49:00 -04:00:00"</span><span class="pl-kos">,</span> <span class="pl-c1">&amp;</span>format<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>odt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-07-11 22:49:00.0 -04:00:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Jiff does support a <code>strptime</code>/<code>strftime</code> style API via the
<code>jiff::fmt::strtime</code> module:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::Zoned;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt = Zoned::strptime(
      &quot;%Y-%m-%d %H:%M:%S %:z&quot;,
      &quot;2024-07-11 22:49:00 -04:00:00&quot;,
    )?;
    assert_eq!(zdt.to_string(), &quot;2024-07-11T22:49:00-04:00[-04:00]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-v">Zoned</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt = <span class="pl-smi">Zoned</span><span class="pl-kos">::</span><span class="pl-en">strptime</span><span class="pl-kos">(</span>
      <span class="pl-s">"%Y-%m-%d %H:%M:%S %:z"</span><span class="pl-kos">,</span>
      <span class="pl-s">"2024-07-11 22:49:00 -04:00:00"</span><span class="pl-kos">,</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-07-11T22:49:00-04:00[-04:00]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><code>time</code> also supports <code>strptime</code>/<code>strftime</code> style APIs:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use time::OffsetDateTime;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // I don't believe `time` supports `%:z`, so we just drop the colons here.
    let format = time::format_description::parse_strftime_borrowed(
        &quot;%Y-%m-%d %H:%M:%S %z&quot;
    )?;
    let odt = OffsetDateTime::parse(&quot;2024-07-11 22:49:00 -0400&quot;, &amp;format)?;
    assert_eq!(odt.to_string(), &quot;2024-07-11 22:49:00.0 -04:00:00&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-v">OffsetDateTime</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// I don't believe `time` supports `%:z`, so we just drop the colons here.</span>
    <span class="pl-k">let</span> format = time<span class="pl-kos">::</span>format_description<span class="pl-kos">::</span><span class="pl-en">parse_strftime_borrowed</span><span class="pl-kos">(</span>
        <span class="pl-s">"%Y-%m-%d %H:%M:%S %z"</span>
    <span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> odt = <span class="pl-smi">OffsetDateTime</span><span class="pl-kos">::</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-s">"2024-07-11 22:49:00 -0400"</span><span class="pl-kos">,</span> <span class="pl-c1">&amp;</span>format<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>odt<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-07-11 22:49:00.0 -04:00:00"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports rounding datetimes</h3><a id="user-content-jiff-supports-rounding-datetimes" class="anchor" aria-label="Permalink: Jiff supports rounding datetimes" href="#jiff-supports-rounding-datetimes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">We use a <code>Zoned</code> with a <code>TimeZone</code> that has a fixed offset. This is same as
<code>time</code>'s <code>OffsetDateTime</code> type:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, tz::{self, TimeZone}, Unit, Zoned};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let tz = TimeZone::fixed(tz::offset(-4));
    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).to_zoned(tz)?;
    let zdt2 = zdt1.round(Unit::Hour)?;
    assert_eq!(zdt2.to_string(), &quot;2024-07-11T17:00:00-04:00[-04:00]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> tz<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-smi">self</span><span class="pl-kos">,</span> <span class="pl-v">TimeZone</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">,</span> <span class="pl-v">Zoned</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> tz = <span class="pl-smi">TimeZone</span><span class="pl-kos">::</span><span class="pl-en">fixed</span><span class="pl-kos">(</span>tz<span class="pl-kos">::</span><span class="pl-en">offset</span><span class="pl-kos">(</span>-<span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">16</span><span class="pl-kos">,</span> <span class="pl-c1">46</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">to_zoned</span><span class="pl-kos">(</span>tz<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-07-11T17:00:00-04:00[-04:00]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Note though that because Jiff has support for time zones, you generally
shouldn't need to (and shouldn't <em>want</em> to) use fixed offset datetimes. It's
because they don't take time zone rules into account and thus do not provide
DST safe arithmetic. Instead, the code above should be written like this
(unless you have a very specific reason to do otherwise):</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // Can also use `.to_zoned(TimeZone::system())` to use your system's
    // default time zone.
    let zdt1 = date(2024, 7, 11).at(16, 46, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = zdt1.round(Unit::Hour)?;
    assert_eq!(zdt2.to_string(), &quot;2024-07-11T17:00:00-04:00[America/New_York]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Can also use `.to_zoned(TimeZone::system())` to use your system's</span>
    <span class="pl-c">// default time zone.</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">16</span><span class="pl-kos">,</span> <span class="pl-c1">46</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2024-07-11T17:00:00-04:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">From here on, we won't use fixed offset datetimes in order to avoid encouraging
their use.</p>
<p dir="auto">The <code>time</code> crate has no rounding APIs.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports rounding durations</h3><a id="user-content-jiff-supports-rounding-durations-1" class="anchor" aria-label="Permalink: Jiff supports rounding durations" href="#jiff-supports-rounding-durations-1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">In Jiff, one can round the duration computed between two datetimes</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, RoundMode, ToSpan, Unit, ZonedDifference};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2001, 11, 18).at(8, 30, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = date(2024, 7, 11).at(22, 38, 0, 0).in_tz(&quot;America/New_York&quot;)?;

    let round_options = ZonedDifference::new(&amp;zdt2)
        .largest(Unit::Year)
        .smallest(Unit::Day)
        .mode(RoundMode::HalfExpand);
    let span = zdt1.until(round_options)?;
    assert_eq!(span, 22.years().months(7).days(24).fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">RoundMode</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">,</span> <span class="pl-v">ZonedDifference</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2001</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">,</span> <span class="pl-c1">18</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">8</span><span class="pl-kos">,</span> <span class="pl-c1">30</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">22</span><span class="pl-kos">,</span> <span class="pl-c1">38</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>

    <span class="pl-k">let</span> round_options = <span class="pl-smi">ZonedDifference</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span>zdt2<span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Year</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">smallest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Day</span><span class="pl-kos">)</span>
        <span class="pl-kos">.</span><span class="pl-en">mode</span><span class="pl-kos">(</span><span class="pl-smi">RoundMode</span><span class="pl-kos">::</span><span class="pl-v">HalfExpand</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span = zdt1<span class="pl-kos">.</span><span class="pl-en">until</span><span class="pl-kos">(</span>round_options<span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">,</span> <span class="pl-c1">22</span><span class="pl-kos">.</span>years<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>months<span class="pl-kos">(</span><span class="pl-c1">7</span><span class="pl-kos">)</span><span class="pl-kos">.</span>days<span class="pl-kos">(</span><span class="pl-c1">24</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code>time</code> crate has no rounding APIs.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff provides support for calendar arithmetic</h3><a id="user-content-jiff-provides-support-for-calendar-arithmetic" class="anchor" aria-label="Permalink: Jiff provides support for calendar arithmetic" href="#jiff-provides-support-for-calendar-arithmetic"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">With Jiff, you can add durations with calendar units:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{civil::date, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let zdt1 = date(2024, 7, 11).at(21, 0, 0, 0).in_tz(&quot;America/New_York&quot;)?;
    let zdt2 = zdt1.checked_add(2.years().months(6).days(1))?;
    assert_eq!(zdt2.to_string(), &quot;2027-01-12T21:00:00-05:00[America/New_York]&quot;);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span>civil<span class="pl-kos">::</span>date<span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> zdt1 = <span class="pl-en">date</span><span class="pl-kos">(</span><span class="pl-c1">2024</span><span class="pl-kos">,</span> <span class="pl-c1">7</span><span class="pl-kos">,</span> <span class="pl-c1">11</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">at</span><span class="pl-kos">(</span><span class="pl-c1">21</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">in_tz</span><span class="pl-kos">(</span><span class="pl-s">"America/New_York"</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> zdt2 = zdt1<span class="pl-kos">.</span><span class="pl-en">checked_add</span><span class="pl-kos">(</span><span class="pl-c1">2</span><span class="pl-kos">.</span><span class="pl-en">years</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">months</span><span class="pl-kos">(</span><span class="pl-c1">6</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">days</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>zdt2<span class="pl-kos">.</span>to_string<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s">"2027-01-12T21:00:00-05:00[America/New_York]"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code>time</code> crate does provide a way to construct a <code>Duration</code> from units of
days via <code>Duration::days</code>, but this of course requires assuming that all days
are 24 hours long. And <code>time</code> does not support adding years or months.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff supports conveniently re-balancing durations</h3><a id="user-content-jiff-supports-conveniently-re-balancing-durations" class="anchor" aria-label="Permalink: Jiff supports conveniently re-balancing durations" href="#jiff-supports-conveniently-re-balancing-durations"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Aside from calendar arithmetic, Jiff also supports re-balancing durations
based on what you want the largest unit to be:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{SpanRound, ToSpan, Unit};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    // Balance down to seconds.
    let span1 = 4.hours().minutes(36).seconds(59);
    let span2 = span1.round(SpanRound::new().largest(Unit::Second))?;
    assert_eq!(span2, 16_619.seconds().fieldwise());

    // Now go back by balancing up to hours.
    let span1 = 16_619.seconds();
    let span2 = span1.round(SpanRound::new().largest(Unit::Hour))?;
    assert_eq!(span2, 4.hours().minutes(36).seconds(59).fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">SpanRound</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">,</span> <span class="pl-v">Unit</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Balance down to seconds.</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">4</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-c1">36</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">seconds</span><span class="pl-kos">(</span><span class="pl-c1">59</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span><span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Second</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">16_619</span><span class="pl-kos">.</span>seconds<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-c">// Now go back by balancing up to hours.</span>
    <span class="pl-k">let</span> span1 = <span class="pl-c1">16_619</span><span class="pl-kos">.</span><span class="pl-en">seconds</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> span2 = span1<span class="pl-kos">.</span><span class="pl-en">round</span><span class="pl-kos">(</span><span class="pl-smi">SpanRound</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">largest</span><span class="pl-kos">(</span><span class="pl-smi">Unit</span><span class="pl-kos">::</span><span class="pl-v">Hour</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span2<span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">.</span>hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>minutes<span class="pl-kos">(</span><span class="pl-c1">36</span><span class="pl-kos">)</span><span class="pl-kos">.</span>seconds<span class="pl-kos">(</span><span class="pl-c1">59</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code>time</code> crate's <code>Duration</code> type can go from bigger units down to smaller
units easily enough:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use time::{ext::NumericalDuration, Duration};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let span = 4.hours() + 36.minutes() + 59.seconds();
    assert_eq!(span.whole_seconds(), 16_619);
    Ok(())
}"><pre><span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>ext<span class="pl-kos">::</span><span class="pl-v">NumericalDuration</span><span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> span = <span class="pl-c1">4</span><span class="pl-kos">.</span><span class="pl-en">hours</span><span class="pl-kos">(</span><span class="pl-kos">)</span> + <span class="pl-c1">36</span><span class="pl-kos">.</span><span class="pl-en">minutes</span><span class="pl-kos">(</span><span class="pl-kos">)</span> + <span class="pl-c1">59</span><span class="pl-kos">.</span><span class="pl-en">seconds</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_seconds<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">16_619</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">But going from smaller units back up to larger units is difficult:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use time::{ext::NumericalDuration, Duration};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let span = 16_619.seconds();
    assert_eq!(span.whole_hours(), 4);
    assert_eq!(span.whole_minutes(), 276);
    assert_eq!(span.whole_seconds(), 16_619);

    Ok(())
}"><pre><span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>ext<span class="pl-kos">::</span><span class="pl-v">NumericalDuration</span><span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> span = <span class="pl-c1">16_619</span><span class="pl-kos">.</span><span class="pl-en">seconds</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_minutes<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">276</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_seconds<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">16_619</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Notice that the accessors just report how many whole units the span is. You
can't get the span broken down into smaller units. To achieve that, you need to
do the arithmetic yourself:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use time::{convert::{Hour, Minute, Second}, ext::NumericalDuration, Duration};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let mut span = 16_619.seconds();
    assert_eq!(span.whole_hours(), 4);
    assert_eq!(span.whole_minutes() % Minute::per(Hour) as i64, 36);
    assert_eq!(span.whole_seconds() % Second::per(Minute) as i64, 59);

    Ok(())
}"><pre><span class="pl-k">use</span> time<span class="pl-kos">::</span><span class="pl-kos">{</span>convert<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Hour</span><span class="pl-kos">,</span> <span class="pl-v">Minute</span><span class="pl-kos">,</span> <span class="pl-v">Second</span><span class="pl-kos">}</span><span class="pl-kos">,</span> ext<span class="pl-kos">::</span><span class="pl-v">NumericalDuration</span><span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-k">mut</span> span = <span class="pl-c1">16_619</span><span class="pl-kos">.</span><span class="pl-en">seconds</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_hours<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_minutes<span class="pl-kos">(</span><span class="pl-kos">)</span> % <span class="pl-v">Minute</span><span class="pl-kos">::</span>per<span class="pl-kos">(</span><span class="pl-v">Hour</span><span class="pl-kos">)</span> <span class="pl-k">as</span> <span class="pl-smi">i64</span><span class="pl-kos">,</span> <span class="pl-c1">36</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">.</span>whole_seconds<span class="pl-kos">(</span><span class="pl-kos">)</span> % <span class="pl-v">Second</span><span class="pl-kos">::</span>per<span class="pl-kos">(</span><span class="pl-v">Minute</span><span class="pl-kos">)</span> <span class="pl-k">as</span> <span class="pl-smi">i64</span><span class="pl-kos">,</span> <span class="pl-c1">59</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff is generally faster than <code>time</code></h3><a id="user-content-jiff-is-generally-faster-than-time" class="anchor" aria-label="Permalink: Jiff is generally faster than time" href="#jiff-is-generally-faster-than-time"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">When it comes to parsing and printing, Jiff is generally faster than <code>time</code>
although not always. <code>time</code> is sometimes faster than Jiff on date arithmetic,
but not by much. (Some of these may be due to faster equality comparisons on
date values, on which <code>time</code> is legitimately faster at than Jiff at present.)</p>
<p dir="auto">The following results were collected with <code>time 0.3.47</code>.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ cd bench
$ cargo bench -- --save-baseline baseline
[.. snip ..]
$ critcmp base -g '(.*)/(?:jiff|time)$'
group                                                           baseline//time                       baseline//jiff
-----                                                           --------------                       --------------
civil_datetime/add_days/diffyear/duration                       1.00      7.8±0.08ns        ? ?/sec  1.67     12.9±0.19ns        ? ?/sec
civil_datetime/add_days/diffyear/span                                                                1.00     18.0±0.28ns        ? ?/sec
civil_datetime/add_days/sameyear/duration                       1.00      7.8±0.11ns        ? ?/sec  1.66     12.9±0.16ns        ? ?/sec
civil_datetime/add_days/sameyear/span                                                                1.00     18.0±0.25ns        ? ?/sec
date/add_days/diffyear/duration                                 1.00      3.8±0.02ns        ? ?/sec  1.67      6.3±0.04ns        ? ?/sec
date/add_days/diffyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec
date/add_days/one/duration                                      1.00      3.8±0.03ns        ? ?/sec  1.38      5.2±0.03ns        ? ?/sec
date/add_days/one/span                                                                               1.00      5.8±0.06ns        ? ?/sec
date/add_days/sameyear/duration                                 1.00      3.8±0.04ns        ? ?/sec  1.68      6.4±0.07ns        ? ?/sec
date/add_days/sameyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec
date/days_in_month/leap/feb                                     1.90      1.1±0.01ns        ? ?/sec  1.00      0.6±0.03ns        ? ?/sec
date/days_in_month/leap/nofeb                                   2.70      1.0±0.01ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec
date/days_in_month/noleap/feb                                   2.78      1.1±0.02ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec
date/days_in_month/noleap/nofeb                                 2.70      1.0±0.02ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec
date/difference_days/duration                                   1.00      2.1±0.02ns        ? ?/sec  1.41      2.9±0.04ns        ? ?/sec
date/difference_days/span                                                                            1.00      2.4±0.03ns        ? ?/sec
date/tomorrow/diff-month                                        1.00      0.4±0.02ns        ? ?/sec  3.42      1.4±0.01ns        ? ?/sec
date/tomorrow/diff-year                                         1.00      1.0±0.01ns        ? ?/sec  1.59      1.5±0.01ns        ? ?/sec
date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec  2.25      0.9±0.01ns        ? ?/sec
date/yesterday/diff-month                                       1.00      0.4±0.01ns        ? ?/sec  3.65      1.4±0.02ns        ? ?/sec
date/yesterday/diff-year                                        1.00      0.9±0.01ns        ? ?/sec  1.35      1.2±0.02ns        ? ?/sec
date/yesterday/same-month                                       1.00      0.4±0.02ns        ? ?/sec  2.06      0.8±0.01ns        ? ?/sec
datetime/add_years_months_days                                                                       1.00     29.1±0.18ns        ? ?/sec
parse/civil_datetime                                            1.00     12.9±0.19ns        ? ?/sec  1.63     21.1±0.19ns        ? ?/sec
parse/rfc2822                                                   2.24     43.4±1.90ns        ? ?/sec  1.00     19.4±0.15ns        ? ?/sec
parse/strptime/oneshot                                                                               1.00     62.2±0.39ns        ? ?/sec
parse/strptime/prebuilt                                         1.00     73.7±0.91ns        ? ?/sec
print/civil_datetime                                            3.27     37.4±0.32ns        ? ?/sec  1.00     11.4±0.04ns        ? ?/sec
print/rfc2822/buffer                                            1.55     20.4±0.08ns        ? ?/sec  1.00     13.2±0.05ns        ? ?/sec
print/rfc2822/to_string                                         3.61     72.0±1.25ns        ? ?/sec  1.00     19.9±0.06ns        ? ?/sec
print/rfc3339/buffer                                            1.33     22.1±0.29ns        ? ?/sec  1.00     16.7±0.11ns        ? ?/sec
print/rfc3339/to_string                                         2.91     68.1±1.30ns        ? ?/sec  1.00     23.4±0.12ns        ? ?/sec
print/rfc9557/buffer                                                                                 1.00     16.2±0.07ns        ? ?/sec
print/rfc9557/to_string                                                                              1.00     22.6±0.20ns        ? ?/sec
print/strftime/oneshot/buffer                                   6.88    421.5±1.39ns        ? ?/sec  1.00     61.3±0.82ns        ? ?/sec
print/strftime/oneshot/to_string                                5.59    434.0±1.44ns        ? ?/sec  1.00     77.7±0.96ns        ? ?/sec
print/strftime/oneshot/zoned                                                                         1.00     74.6±1.07ns        ? ?/sec
print/strftime/prebuilt/buffer                                  1.00     97.7±0.99ns        ? ?/sec
print/strftime/prebuilt/buffer/bespoke                          1.00    105.8±1.45ns        ? ?/sec
print/strftime/prebuilt/to_string                               1.00    165.3±1.19ns        ? ?/sec
print/strftime/prebuilt/to_string/bespoke                       1.00    175.0±1.79ns        ? ?/sec
timestamp/add_time_secs/duration                                3.82      9.6±0.04ns        ? ?/sec  1.00      2.5±0.03ns        ? ?/sec
timestamp/add_time_secs/span                                                                         1.00      3.7±0.05ns        ? ?/sec
timestamp/add_time_subsec/duration                              3.33      9.7±0.09ns        ? ?/sec  1.00      2.9±0.03ns        ? ?/sec
timestamp/add_time_subsec/span                                                                       1.00      7.8±0.08ns        ? ?/sec
timestamp/every_hour_in_week/byhand                             14.30 1530.8±16.96ns        ? ?/sec  1.00    107.1±0.74ns        ? ?/sec
timestamp/every_hour_in_week/series                                                                  1.00    105.8±1.01ns        ? ?/sec
timestamp/from_seconds/integer                                  11.69     4.4±0.03ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec
timestamp/to_civil_datetime_offset_conversion                   1.00      3.9±0.03ns        ? ?/sec  1.49      5.8±0.04ns        ? ?/sec
timestamp/to_civil_datetime_offset_holistic                     1.00      4.6±0.03ns        ? ?/sec  1.04      4.8±0.04ns        ? ?/sec
zoned/fixed_offset_add_time/duration                            1.00      9.6±0.09ns        ? ?/sec  1.06     10.3±0.08ns        ? ?/sec
zoned/fixed_offset_add_time/span                                                                     1.00     16.9±0.12ns        ? ?/sec
zoned/fixed_offset_to_civil_datetime                            1.00      0.6±0.00ns        ? ?/sec  7.32      4.2±0.01ns        ? ?/sec
zoned/fixed_offset_to_timestamp                                 6.08      1.8±0.02ns        ? ?/sec  1.00      0.3±0.01ns        ? ?/sec"><pre lang="text" class="notranslate"><code>$ cd bench
$ cargo bench -- --save-baseline baseline
[.. snip ..]
$ critcmp base -g '(.*)/(?:jiff|time)$'
group                                                           baseline//time                       baseline//jiff
-----                                                           --------------                       --------------
civil_datetime/add_days/diffyear/duration                       1.00      7.8±0.08ns        ? ?/sec  1.67     12.9±0.19ns        ? ?/sec
civil_datetime/add_days/diffyear/span                                                                1.00     18.0±0.28ns        ? ?/sec
civil_datetime/add_days/sameyear/duration                       1.00      7.8±0.11ns        ? ?/sec  1.66     12.9±0.16ns        ? ?/sec
civil_datetime/add_days/sameyear/span                                                                1.00     18.0±0.25ns        ? ?/sec
date/add_days/diffyear/duration                                 1.00      3.8±0.02ns        ? ?/sec  1.67      6.3±0.04ns        ? ?/sec
date/add_days/diffyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec
date/add_days/one/duration                                      1.00      3.8±0.03ns        ? ?/sec  1.38      5.2±0.03ns        ? ?/sec
date/add_days/one/span                                                                               1.00      5.8±0.06ns        ? ?/sec
date/add_days/sameyear/duration                                 1.00      3.8±0.04ns        ? ?/sec  1.68      6.4±0.07ns        ? ?/sec
date/add_days/sameyear/span                                                                          1.00      4.9±0.05ns        ? ?/sec
date/days_in_month/leap/feb                                     1.90      1.1±0.01ns        ? ?/sec  1.00      0.6±0.03ns        ? ?/sec
date/days_in_month/leap/nofeb                                   2.70      1.0±0.01ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec
date/days_in_month/noleap/feb                                   2.78      1.1±0.02ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec
date/days_in_month/noleap/nofeb                                 2.70      1.0±0.02ns        ? ?/sec  1.00      0.4±0.00ns        ? ?/sec
date/difference_days/duration                                   1.00      2.1±0.02ns        ? ?/sec  1.41      2.9±0.04ns        ? ?/sec
date/difference_days/span                                                                            1.00      2.4±0.03ns        ? ?/sec
date/tomorrow/diff-month                                        1.00      0.4±0.02ns        ? ?/sec  3.42      1.4±0.01ns        ? ?/sec
date/tomorrow/diff-year                                         1.00      1.0±0.01ns        ? ?/sec  1.59      1.5±0.01ns        ? ?/sec
date/tomorrow/same-month                                        1.00      0.4±0.00ns        ? ?/sec  2.25      0.9±0.01ns        ? ?/sec
date/yesterday/diff-month                                       1.00      0.4±0.01ns        ? ?/sec  3.65      1.4±0.02ns        ? ?/sec
date/yesterday/diff-year                                        1.00      0.9±0.01ns        ? ?/sec  1.35      1.2±0.02ns        ? ?/sec
date/yesterday/same-month                                       1.00      0.4±0.02ns        ? ?/sec  2.06      0.8±0.01ns        ? ?/sec
datetime/add_years_months_days                                                                       1.00     29.1±0.18ns        ? ?/sec
parse/civil_datetime                                            1.00     12.9±0.19ns        ? ?/sec  1.63     21.1±0.19ns        ? ?/sec
parse/rfc2822                                                   2.24     43.4±1.90ns        ? ?/sec  1.00     19.4±0.15ns        ? ?/sec
parse/strptime/oneshot                                                                               1.00     62.2±0.39ns        ? ?/sec
parse/strptime/prebuilt                                         1.00     73.7±0.91ns        ? ?/sec
print/civil_datetime                                            3.27     37.4±0.32ns        ? ?/sec  1.00     11.4±0.04ns        ? ?/sec
print/rfc2822/buffer                                            1.55     20.4±0.08ns        ? ?/sec  1.00     13.2±0.05ns        ? ?/sec
print/rfc2822/to_string                                         3.61     72.0±1.25ns        ? ?/sec  1.00     19.9±0.06ns        ? ?/sec
print/rfc3339/buffer                                            1.33     22.1±0.29ns        ? ?/sec  1.00     16.7±0.11ns        ? ?/sec
print/rfc3339/to_string                                         2.91     68.1±1.30ns        ? ?/sec  1.00     23.4±0.12ns        ? ?/sec
print/rfc9557/buffer                                                                                 1.00     16.2±0.07ns        ? ?/sec
print/rfc9557/to_string                                                                              1.00     22.6±0.20ns        ? ?/sec
print/strftime/oneshot/buffer                                   6.88    421.5±1.39ns        ? ?/sec  1.00     61.3±0.82ns        ? ?/sec
print/strftime/oneshot/to_string                                5.59    434.0±1.44ns        ? ?/sec  1.00     77.7±0.96ns        ? ?/sec
print/strftime/oneshot/zoned                                                                         1.00     74.6±1.07ns        ? ?/sec
print/strftime/prebuilt/buffer                                  1.00     97.7±0.99ns        ? ?/sec
print/strftime/prebuilt/buffer/bespoke                          1.00    105.8±1.45ns        ? ?/sec
print/strftime/prebuilt/to_string                               1.00    165.3±1.19ns        ? ?/sec
print/strftime/prebuilt/to_string/bespoke                       1.00    175.0±1.79ns        ? ?/sec
timestamp/add_time_secs/duration                                3.82      9.6±0.04ns        ? ?/sec  1.00      2.5±0.03ns        ? ?/sec
timestamp/add_time_secs/span                                                                         1.00      3.7±0.05ns        ? ?/sec
timestamp/add_time_subsec/duration                              3.33      9.7±0.09ns        ? ?/sec  1.00      2.9±0.03ns        ? ?/sec
timestamp/add_time_subsec/span                                                                       1.00      7.8±0.08ns        ? ?/sec
timestamp/every_hour_in_week/byhand                             14.30 1530.8±16.96ns        ? ?/sec  1.00    107.1±0.74ns        ? ?/sec
timestamp/every_hour_in_week/series                                                                  1.00    105.8±1.01ns        ? ?/sec
timestamp/from_seconds/integer                                  11.69     4.4±0.03ns        ? ?/sec  1.00      0.4±0.01ns        ? ?/sec
timestamp/to_civil_datetime_offset_conversion                   1.00      3.9±0.03ns        ? ?/sec  1.49      5.8±0.04ns        ? ?/sec
timestamp/to_civil_datetime_offset_holistic                     1.00      4.6±0.03ns        ? ?/sec  1.04      4.8±0.04ns        ? ?/sec
zoned/fixed_offset_add_time/duration                            1.00      9.6±0.09ns        ? ?/sec  1.06     10.3±0.08ns        ? ?/sec
zoned/fixed_offset_add_time/span                                                                     1.00     16.9±0.12ns        ? ?/sec
zoned/fixed_offset_to_civil_datetime                            1.00      0.6±0.00ns        ? ?/sec  7.32      4.2±0.01ns        ? ?/sec
zoned/fixed_offset_to_timestamp                                 6.08      1.8±0.02ns        ? ?/sec  1.00      0.3±0.01ns        ? ?/sec
</code></pre></div>
<p dir="auto">Questions about benchmarks are welcome in
<a href="https://github.com/BurntSushi/jiff/discussions">Discussions on GitHub</a>.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto"><a href="https://docs.rs/hifitime" rel="nofollow"><code>hifitime</code></a> (v3.9.0)</h2><a id="user-content-hifitime-v390" class="anchor" aria-label="Permalink: hifitime (v3.9.0)" href="#hifitime-v390"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><code>hifitime</code> is a datetime library with a focus on engineering and scientific
calculations where general relativity and time dilation matter. It supports
conversion between many different time scales: TAI, Terrestrial Time, UTC, GPST
and more. It also supports leap seconds.</p>
<p dir="auto">For the following comparisons, a <code>Cargo.toml</code> with the following dependencies
should be able to run any of the programs in this section:</p>
<div class="highlight highlight-source-toml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="anyhow = &quot;1.0.81&quot;
hifitime = &quot;3.9.0&quot;
jiff = { version = &quot;0.2.0&quot;, features = [&quot;serde&quot;] }"><pre><span class="pl-smi">anyhow</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.81<span class="pl-pds">"</span></span>
<span class="pl-smi">hifitime</span> = <span class="pl-s"><span class="pl-pds">"</span>3.9.0<span class="pl-pds">"</span></span>
<span class="pl-smi">jiff</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.2.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>serde<span class="pl-pds">"</span></span>] }</pre></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Time zone database integration</h3><a id="user-content-time-zone-database-integration-2" class="anchor" aria-label="Permalink: Time zone database integration" href="#time-zone-database-integration-2"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Like the <code>time</code> crate, <code>hifitime</code> does not support time zones and does not have
any integration with the Time Zone Database. <code>hifitime</code> doesn't have any
equivalent to <code>OffsetDateTime</code> like in <code>time</code> either. The only datetime type
that <code>hifitime</code> has is <code>Epoch</code>, and it is an absolute time. While you can
convert between it and civil time (assuming civil time is in UTC), there is no
data type in <code>hifitime</code> for representing civil time.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto"><code>hifitime</code> supports leap seconds</h3><a id="user-content-hifitime-supports-leap-seconds" class="anchor" aria-label="Permalink: hifitime supports leap seconds" href="#hifitime-supports-leap-seconds"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">In particular, when computing a duration from two <code>Epoch</code> values that spans
a positive leap second (a second gets repeated), <code>hifitime</code> will correctly
report the accurate duration. With that said, to get an accurate duration, one
of the two time scales has to be converted to to TAI (or another time scale
which does not have leap seconds):</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use hifitime::{Duration, Epoch, TimeScale};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let e1: Epoch = &quot;2015-06-30T23:00:00 UTC&quot;.parse()?;
    let e2: Epoch = &quot;2015-07-01T00:00:00 UTC&quot;.parse()?;
    let e2 = e2.to_time_scale(TimeScale::TAI);

    let duration = e2 - e1;
    assert_eq!(duration, Duration::from_seconds(3_601.0));

    Ok(())
}"><pre><span class="pl-k">use</span> hifitime<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Duration</span><span class="pl-kos">,</span> <span class="pl-v">Epoch</span><span class="pl-kos">,</span> <span class="pl-v">TimeScale</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> e1<span class="pl-kos">:</span> <span class="pl-smi">Epoch</span> = <span class="pl-s">"2015-06-30T23:00:00 UTC"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> e2<span class="pl-kos">:</span> <span class="pl-smi">Epoch</span> = <span class="pl-s">"2015-07-01T00:00:00 UTC"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> e2 = e2<span class="pl-kos">.</span><span class="pl-en">to_time_scale</span><span class="pl-kos">(</span><span class="pl-smi">TimeScale</span><span class="pl-kos">::</span><span class="pl-v">TAI</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">let</span> duration = e2 - e1<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>duration<span class="pl-kos">,</span> <span class="pl-v">Duration</span><span class="pl-kos">::</span>from_seconds<span class="pl-kos">(</span><span class="pl-c1">3_601.0</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Jiff, however, <a href="https://github.com/BurntSushi/jiff/issues/7" data-hovercard-type="issue" data-hovercard-url="/BurntSushi/jiff/issues/7/hovercard">does not support leap seconds</a>:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{Timestamp, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let ts1: Timestamp = &quot;2015-06-30T23:00:00Z&quot;.parse()?;
    let ts2: Timestamp = &quot;2015-07-01T00:00:00Z&quot;.parse()?;
    let span = ts2 - ts1;
    assert_eq!(span, 3_600.seconds().fieldwise());

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Timestamp</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> ts1<span class="pl-kos">:</span> <span class="pl-smi">Timestamp</span> = <span class="pl-s">"2015-06-30T23:00:00Z"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> ts2<span class="pl-kos">:</span> <span class="pl-smi">Timestamp</span> = <span class="pl-s">"2015-07-01T00:00:00Z"</span><span class="pl-kos">.</span><span class="pl-en">parse</span><span class="pl-kos">(</span><span class="pl-kos">)</span>?<span class="pl-kos">;</span>
    <span class="pl-k">let</span> span = ts2 - ts1<span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>span<span class="pl-kos">,</span> <span class="pl-c1">3_600</span><span class="pl-kos">.</span>seconds<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span>fieldwise<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">So in this case, Jiff reports <code>3,600</code> seconds as the duration, but the <em>actual</em>
duration was <code>3,601</code> seconds, as reported by <code>hifitime</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Jiff makes checked or saturating arithmetic explicit</h3><a id="user-content-jiff-makes-checked-or-saturating-arithmetic-explicit" class="anchor" aria-label="Permalink: Jiff makes checked or saturating arithmetic explicit" href="#jiff-makes-checked-or-saturating-arithmetic-explicit"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">For Jiff, whether you want to saturate or not is an explicit part of the API.
And implementations of the <code>Add</code> operator will panic on overflow:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use jiff::{Timestamp, ToSpan};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let ts = Timestamp::MAX;
    assert!(ts.checked_add(1.day()).is_err());
    assert_eq!(ts.saturating_add(1.hour())?, ts);

    Ok(())
}"><pre><span class="pl-k">use</span> jiff<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Timestamp</span><span class="pl-kos">,</span> <span class="pl-v">ToSpan</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> ts = <span class="pl-smi">Timestamp</span><span class="pl-kos">::</span><span class="pl-v">MAX</span><span class="pl-kos">;</span>
    <span class="pl-en">assert</span><span class="pl-en">!</span><span class="pl-kos">(</span>ts<span class="pl-kos">.</span>checked_add<span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span>day<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span>is_err<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>ts<span class="pl-kos">.</span>saturating_add<span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">.</span>hour<span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>?<span class="pl-kos">,</span> ts<span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">In contrast, <code>hifitime</code> appears to use saturating arithmetic everywhere (I've
not been able to find this behavior documented though, so I'm not clear on what
the intended semantics are):</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="use hifitime::{Duration, Epoch};

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let e1 = Epoch::from_unix_seconds(f64::MAX);
    let e2 = e1 + Duration::from_days(1.0);
    assert_eq!(e1, e2);

    Ok(())
}"><pre><span class="pl-k">use</span> hifitime<span class="pl-kos">::</span><span class="pl-kos">{</span><span class="pl-v">Duration</span><span class="pl-kos">,</span> <span class="pl-v">Epoch</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> -&gt; anyhow<span class="pl-kos">::</span><span class="pl-smi">Result</span><span class="pl-kos">&lt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> e1 = <span class="pl-smi">Epoch</span><span class="pl-kos">::</span><span class="pl-en">from_unix_seconds</span><span class="pl-kos">(</span>f64<span class="pl-kos">::</span><span class="pl-v">MAX</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">let</span> e2 = e1 + <span class="pl-smi">Duration</span><span class="pl-kos">::</span><span class="pl-en">from_days</span><span class="pl-kos">(</span><span class="pl-c1">1.0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">assert_eq</span><span class="pl-en">!</span><span class="pl-kos">(</span>e1<span class="pl-kos">,</span> e2<span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-en">Ok</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto"><a href="https://docs.rs/icu" rel="nofollow"><code>icu</code></a> (v1.5.0)</h2><a id="user-content-icu-v150" class="anchor" aria-label="Permalink: icu (v1.5.0)" href="#icu-v150"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">The ICU4X project fulfils a slightly different need than <code>jiff</code>. Its main
features are calendrical calculations (<code>icu::calendar</code>), supporting conversions
between different calendar systems such as Gregorian, Buddhist, Islamic,
Japanese, etc., as well as localized datetime formatting (<code>icu::datetime</code>).</p>
<p dir="auto">It does not perform datetime or time-zone arithmetic, and does not have a
timestamp or duration type.</p>
<p dir="auto"><code>icu</code> can be used to complement <code>jiff</code> when localized date formatting or
calendar conversions are required. To facilitate this, the
<a href="https://docs.rs/jiff-icu" rel="nofollow"><code>jiff-icu</code></a> crate makes conversions between Jiff
and ICU4X data types seamless. For example, to do localization starting from
a Jiff data type:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="use icu::{
    calendar::{japanese::Japanese, DateTime},
    datetime::TypedDateTimeFormatter,
    locid::locale,
};
use jiff::Timestamp;
use jiff_icu::ConvertFrom as _;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let ts: Timestamp = &quot;2024-09-10T23:37:20Z&quot;.parse()?;
    let zoned = ts.in_tz(&quot;Asia/Tokyo&quot;)?;

    // Create ICU datetime.
    let datetime = DateTime::convert_from(zoned.datetime());

    // Convert to Japanese calendar.
    let japanese_datetime = DateTime::new_from_iso(datetime, Japanese::new());

    // Format for the en-GB locale.
    let formatter = TypedDateTimeFormatter::try_new(
        &amp;locale!(&quot;en-GB&quot;).into(),
        Default::default(),
    )?;

    // Assert that we get the expected result.
    assert_eq!(
        formatter.format(&amp;japanese_datetime).to_string(),
        &quot;Sept 11, 6 Reiwa, 08:37:20&quot;,
    );

    Ok(())
}"><pre lang="text" class="notranslate"><code>use icu::{
    calendar::{japanese::Japanese, DateTime},
    datetime::TypedDateTimeFormatter,
    locid::locale,
};
use jiff::Timestamp;
use jiff_icu::ConvertFrom as _;

fn main() -&gt; anyhow::Result&lt;()&gt; {
    let ts: Timestamp = "2024-09-10T23:37:20Z".parse()?;
    let zoned = ts.in_tz("Asia/Tokyo")?;

    // Create ICU datetime.
    let datetime = DateTime::convert_from(zoned.datetime());

    // Convert to Japanese calendar.
    let japanese_datetime = DateTime::new_from_iso(datetime, Japanese::new());

    // Format for the en-GB locale.
    let formatter = TypedDateTimeFormatter::try_new(
        &amp;locale!("en-GB").into(),
        Default::default(),
    )?;

    // Assert that we get the expected result.
    assert_eq!(
        formatter.format(&amp;japanese_datetime).to_string(),
        "Sept 11, 6 Reiwa, 08:37:20",
    );

    Ok(())
}
</code></pre></div>
<p dir="auto">The above example requires the following dependency specifications:</p>
<div class="highlight highlight-source-toml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="anyhow = &quot;1.0.81&quot;
icu = { version = &quot;1.5.0&quot;, features = [&quot;std&quot;] }
jiff = { version = &quot;0.1.0&quot;, features = [&quot;serde&quot;] }
jiff-icu = { version = &quot;0.1.0&quot; }"><pre><span class="pl-smi">anyhow</span> = <span class="pl-s"><span class="pl-pds">"</span>1.0.81<span class="pl-pds">"</span></span>
<span class="pl-smi">icu</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>1.5.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>std<span class="pl-pds">"</span></span>] }
<span class="pl-smi">jiff</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.1.0<span class="pl-pds">"</span></span>, <span class="pl-smi">features</span> = [<span class="pl-s"><span class="pl-pds">"</span>serde<span class="pl-pds">"</span></span>] }
<span class="pl-smi">jiff-icu</span> = { <span class="pl-smi">version</span> = <span class="pl-s"><span class="pl-pds">"</span>0.1.0<span class="pl-pds">"</span></span> }</pre></div>
</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> </div>
</react-app>




  </div>

</turbo-frame>

    </main>
  </div>

  </div>

          <footer class="footer f6 color-fg-muted color-border-subtle tmp-pt-7 tmp-pb-6 p-responsive" role="contentinfo"  >
  <h2 class='sr-only'>Footer</h2>

  


  <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap">
    <div class="d-flex flex-items-center flex-shrink-0 mx-2">
      <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com">
        <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github">
    <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path>
</svg>
</a>
      <span>
        &copy; 2026 GitHub,&nbsp;Inc.
      </span>
    </div>

    <nav aria-label="Footer">
      <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3>

      <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading">


          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a>
          </li>


            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a>
            </li>

            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a>
            </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a>
          </li>

          
<li class="mx-2" >
  <cookie-consent-link>
    <button
      type="button"
      class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent"
      data-action="click:cookie-consent-link#showConsentManagement"
      data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}"
    >
      Manage cookies
    </button>
  </cookie-consent-link>
</li>

  <li class="mx-2">
    <cookie-consent-link>
      <button
        type="button"
        class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left"
        data-action="click:cookie-consent-link#showConsentManagement"
        data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}"
      >
        Do not share my personal information
      </button>
    </cookie-consent-link>
  </li>

      </ul>
    </nav>
  </div>
</footer>



    <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999"
      data-locale="en"
      data-initial-cookie-consent-allowed=""
      data-cookie-consent-required="true"
    ></ghcc-consent>




  <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden>
    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    You can’t perform that action at this time.
  </div>

    <template id="site-details-dialog">
  <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open>
    <summary role="button" aria-label="Close dialog"></summary>
    <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal">
      <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
      </button>
      <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div>
    </details-dialog>
  </details>
</template>

    <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;">
  <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;">
  </div>
</div>

    <template id="snippet-clipboard-copy-button">
  <div class="zeroclipboard-container position-absolute right-0 top-0">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>
<template id="snippet-clipboard-copy-button-unpositioned">
  <div class="zeroclipboard-container">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>




    </div>
    <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div>
    <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div>
  </body>
</html>

