From 988bd3d2c40b3ad4de8517c992b448acd33cdd70 Mon Sep 17 00:00:00 2001 From: Jesse Van Volkinburg <42327429+vanvoljg@users.noreply.github.com> Date: Thu, 5 Jan 2023 08:35:49 -0800 Subject: [PATCH 1/2] Dependency updates 20230104 (#276) * Bump actions/cache from 2.1.6 to 3.2.2 * Bump codecov/codecov-action from 1.5.0 to 3.1.1 * Bump erlef/setup-elixir from 1.7 to 1.15 * Bump actions/checkout from 2.3.4 to 3.2.0 * Bump excoveralls from 0.14.1 to 0.15.1 * Bump dialyxir from 1.1.0 to 1.2.0 * Bump ex_doc 0.24.2 => 0.29.1 (minor), earmark_parser 1.4.13 => 1.4.29, makeup 1.0.5 => 1.1.0, makeup_elixir 0.15.1 => 0.16.0 (minor), nimble_parsec 1.1.0 => 1.2.3 * Bump credo 1.5.6 => 1.6.7, bunt 0.2.0 => 0.2.1 * Bump timex 3.7.5 => 3.7.9, gettext 0.18.2 => 0.20.0 (minor), tzdata 1.1.0 => 1.1.1 * set-output is deprecated, use env "files" * bump Erlang/OTP and Elixir versions for CI * address credo warnings * map_join is more efficient than `map |> join` * fixed typespecs in test helper * remove deprecated Mix.Config usage * version 0.10.2 * add missing tests for string builder * Update CHANGELOG.md * use README for docs landing * remove broken image --- .github/workflows/ci.yml | 82 +++++++++++++-------------- CHANGELOG.md | 16 +++++- README.md | 2 +- config/config.exs | 3 - config/dev.exs | 1 - config/docs.exs | 1 - config/test.exs | 1 - lib/cocktail/builder/i_calendar.ex | 12 ++-- lib/cocktail/builder/string.ex | 3 +- mix.exs | 8 +-- mix.lock | 30 +++++----- test/cocktail/builder/string_test.exs | 24 ++++++++ test/cocktail/monthly_test.exs | 4 +- 13 files changed, 108 insertions(+), 79 deletions(-) delete mode 100644 config/config.exs delete mode 100644 config/dev.exs delete mode 100644 config/docs.exs delete mode 100644 config/test.exs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1badba..82b2f5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,8 @@ on: env: MIX_ENV: test - OTP_VERSION_SPEC: "24.x" - ELIXIR_VERSION_SPEC: "1.12.x" + OTP_VERSION_SPEC: "25.x" + ELIXIR_VERSION_SPEC: "1.14.x" jobs: format: @@ -16,8 +16,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2.3.4 - - uses: erlef/setup-elixir@v1.7 + - uses: actions/checkout@v3.2.0 + - uses: erlef/setup-elixir@v1.15 id: setup with: otp-version: ${{ env.OTP_VERSION_SPEC }} @@ -32,8 +32,8 @@ jobs: steps: # shared steps - - uses: actions/checkout@v2.3.4 - - uses: erlef/setup-elixir@v1.7 + - uses: actions/checkout@v3.2.0 + - uses: erlef/setup-elixir@v1.15 id: setup with: otp-version: ${{ env.OTP_VERSION_SPEC }} @@ -41,19 +41,19 @@ jobs: - name: Cache Keys id: keys run: | - echo ::set-output name=deps_key::deps-${{ runner.os }} - echo ::set-output name=lockfile_key::${{ hashFiles('mix.lock') }} - echo ::set-output name=build_key::build-${{ runner.os }}-${{ env.MIX_ENV }} - echo ::set-output name=version_key::${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }} - echo ::set-output name=files_key::${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }} - - uses: actions/cache@v2.1.6 + echo "deps_key=deps-${{ runner.os }}" >> $GITHUB_OUTPUT + echo "lockfile_key=${{ hashFiles('mix.lock') }}" >> $GITHUB_OUTPUT + echo "build_key=build-${{ runner.os }}-${{ env.MIX_ENV }}" >> $GITHUB_OUTPUT + echo "version_key=${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }}" >> $GITHUB_OUTPUT + echo "files_key=${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }}" >> $GITHUB_OUTPUT + - uses: actions/cache@v3.2.2 id: deps_cache with: path: deps key: ${{ steps.keys.outputs.deps_key }}-${{ steps.keys.outputs.lockfile_key }} restore-keys: | ${{ steps.keys.outputs.deps_key }}- - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v3.2.2 id: build_cache with: path: _build @@ -77,8 +77,8 @@ jobs: steps: # shared steps - - uses: actions/checkout@v2.3.4 - - uses: erlef/setup-elixir@v1.7 + - uses: actions/checkout@v3.2.0 + - uses: erlef/setup-elixir@v1.15 id: setup with: otp-version: ${{ env.OTP_VERSION_SPEC }} @@ -86,19 +86,19 @@ jobs: - name: Cache Keys id: keys run: | - echo ::set-output name=deps_key::deps-${{ runner.os }} - echo ::set-output name=lockfile_key::${{ hashFiles('mix.lock') }} - echo ::set-output name=build_key::build-${{ runner.os }}-${{ env.MIX_ENV }} - echo ::set-output name=version_key::${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }} - echo ::set-output name=files_key::${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }} - - uses: actions/cache@v2.1.6 + echo "deps_key=deps-${{ runner.os }}" >> $GITHUB_OUTPUT + echo "lockfile_key=${{ hashFiles('mix.lock') }}" >> $GITHUB_OUTPUT + echo "build_key=build-${{ runner.os }}-${{ env.MIX_ENV }}" >> $GITHUB_OUTPUT + echo "version_key=${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }}" >> $GITHUB_OUTPUT + echo "files_key=${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }}" >> $GITHUB_OUTPUT + - uses: actions/cache@v3.2.2 id: deps_cache with: path: deps key: ${{ steps.keys.outputs.deps_key }}-${{ steps.keys.outputs.lockfile_key }} restore-keys: | ${{ steps.keys.outputs.deps_key }}- - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v3.2.2 id: build_cache with: path: _build @@ -115,7 +115,7 @@ jobs: # job steps - name: Run tests run: mix coveralls.json - - uses: codecov/codecov-action@v1.5.0 + - uses: codecov/codecov-action@v3.1.1 with: fail_ci_if_error: true @@ -128,8 +128,8 @@ jobs: steps: # shared steps - - uses: actions/checkout@v2.3.4 - - uses: erlef/setup-elixir@v1.7 + - uses: actions/checkout@v3.2.0 + - uses: erlef/setup-elixir@v1.15 id: setup with: otp-version: ${{ env.OTP_VERSION_SPEC }} @@ -137,19 +137,19 @@ jobs: - name: Cache Keys id: keys run: | - echo ::set-output name=deps_key::deps-${{ runner.os }} - echo ::set-output name=lockfile_key::${{ hashFiles('mix.lock') }} - echo ::set-output name=build_key::build-${{ runner.os }}-${{ env.MIX_ENV }} - echo ::set-output name=version_key::${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }} - echo ::set-output name=files_key::${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }} - - uses: actions/cache@v2.1.6 + echo "deps_key=deps-${{ runner.os }}" >> $GITHUB_OUTPUT + echo "lockfile_key=${{ hashFiles('mix.lock') }}" >> $GITHUB_OUTPUT + echo "build_key=build-${{ runner.os }}-${{ env.MIX_ENV }}" >> $GITHUB_OUTPUT + echo "version_key=${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }}" >> $GITHUB_OUTPUT + echo "files_key=${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }}" >> $GITHUB_OUTPUT + - uses: actions/cache@v3.2.2 id: deps_cache with: path: deps key: ${{ steps.keys.outputs.deps_key }}-${{ steps.keys.outputs.lockfile_key }} restore-keys: | ${{ steps.keys.outputs.deps_key }}- - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v3.2.2 id: build_cache with: path: _build @@ -177,8 +177,8 @@ jobs: steps: # shared steps - - uses: actions/checkout@v2.3.4 - - uses: erlef/setup-elixir@v1.7 + - uses: actions/checkout@v3.2.0 + - uses: erlef/setup-elixir@v1.15 id: setup with: otp-version: ${{ env.OTP_VERSION_SPEC }} @@ -186,19 +186,19 @@ jobs: - name: Cache Keys id: keys run: | - echo ::set-output name=deps_key::deps-${{ runner.os }} - echo ::set-output name=lockfile_key::${{ hashFiles('mix.lock') }} - echo ::set-output name=build_key::build-${{ runner.os }}-${{ env.MIX_ENV }} - echo ::set-output name=version_key::${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }} - echo ::set-output name=files_key::${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }} - - uses: actions/cache@v2.1.6 + echo "deps_key=deps-${{ runner.os }}" >> $GITHUB_OUTPUT + echo "lockfile_key=${{ hashFiles('mix.lock') }}" >> $GITHUB_OUTPUT + echo "build_key=build-${{ runner.os }}-${{ env.MIX_ENV }}" >> $GITHUB_OUTPUT + echo "version_key=${{ steps.setup.outputs['otp-version'] }}-${{ steps.setup.outputs['elixir-version'] }}" >> $GITHUB_OUTPUT + echo "files_key=${{ hashFiles('lib/**/*.ex','test/**/*.ex','mix.lock') }}" >> $GITHUB_OUTPUT + - uses: actions/cache@v3.2.2 id: deps_cache with: path: deps key: ${{ steps.keys.outputs.deps_key }}-${{ steps.keys.outputs.lockfile_key }} restore-keys: | ${{ steps.keys.outputs.deps_key }}- - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v3.2.2 id: build_cache with: path: _build diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c3420..4ff02ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased][] +## [0.10.2][] - 2023-01-04 + +- Updated GitHub Actions steps to latest versions: + + - `actions/cache` 3.2.2, `actions/checkout` 3.2.0, `erlef/setup-elixir` 1.15, `codecov/codecov-action` 3.1.1 + +- Updated Elixir dependencies: + + - `excoveralls` 0.15.1, `dialyxir` 1.2.0, `ex_doc` 0.29.1, `earmark_parser` 1.4.29, + `makeup` 1.1.0, `makeup_elixir` 0.16.0, `nimble_parsec` 1.2.3, `credo` 1.6.7, + `bunt` 0.2.1, `timex` 3.7.9, `gettext` 0.20.0, `tzdata` 1.1.1 + ## [0.10.0][] - 2021-06-18 ### Added @@ -151,7 +163,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Initial release -[Unreleased]: https://github.com/peek-travel/cocktail/compare/0.10.0...HEAD +[Unreleased]: https://github.com/peek-travel/cocktail/compare/0.10.2...HEAD + +[0.10.2]: https://github.com/peek-travel/cocktail/compare/0.10.0...0.10.2 [0.10.0]: https://github.com/peek-travel/cocktail/compare/0.9.0...0.10.0 diff --git a/README.md b/README.md index afe11be..af7594f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cocktail ![Cocktail](./logo_with_border.png) +# Cocktail [![CI Status](https://github.com/peek-travel/cocktail/workflows/CI/badge.svg)](https://github.com/peek-travel/cocktail/actions) diff --git a/config/config.exs b/config/config.exs deleted file mode 100644 index 8233fe9..0000000 --- a/config/config.exs +++ /dev/null @@ -1,3 +0,0 @@ -use Mix.Config - -import_config "#{Mix.env()}.exs" diff --git a/config/dev.exs b/config/dev.exs deleted file mode 100644 index d2d855e..0000000 --- a/config/dev.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/config/docs.exs b/config/docs.exs deleted file mode 100644 index d2d855e..0000000 --- a/config/docs.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/config/test.exs b/config/test.exs deleted file mode 100644 index d2d855e..0000000 --- a/config/test.exs +++ /dev/null @@ -1 +0,0 @@ -use Mix.Config diff --git a/lib/cocktail/builder/i_calendar.ex b/lib/cocktail/builder/i_calendar.ex index 91a3488..35cf3be 100644 --- a/lib/cocktail/builder/i_calendar.ex +++ b/lib/cocktail/builder/i_calendar.ex @@ -82,7 +82,8 @@ defmodule Cocktail.Builder.ICalendar do """ @spec build_rule(Schedule.t()) :: String.t() def build_rule(schedule) do - Enum.map(schedule.recurrence_rules, &do_build_rule/1) |> Enum.join() + schedule.recurrence_rules + |> Enum.map_join(&do_build_rule/1) end @spec build_time(Cocktail.time(), String.t()) :: String.t() @@ -175,8 +176,7 @@ defmodule Cocktail.Builder.ICalendar do days_list = days |> Enum.sort() - |> Enum.map(&to_string/1) - |> Enum.join(",") + |> Enum.map_join(",", &to_string/1) "BYMONTHDAY=#{days_list}" end @@ -186,8 +186,7 @@ defmodule Cocktail.Builder.ICalendar do days_list = days |> Enum.sort() - |> Enum.map(&by_day/1) - |> Enum.join(",") + |> Enum.map_join(",", &by_day/1) "BYDAY=#{days_list}" end @@ -244,8 +243,7 @@ defmodule Cocktail.Builder.ICalendar do times_list = times |> Enum.sort() - |> Enum.map(&format_erl_time/1) - |> Enum.join(",") + |> Enum.map_join(",", &format_erl_time/1) "X-BYTIME=#{times_list}" end diff --git a/lib/cocktail/builder/string.ex b/lib/cocktail/builder/string.ex index 489f7e0..8b335bb 100644 --- a/lib/cocktail/builder/string.ex +++ b/lib/cocktail/builder/string.ex @@ -31,8 +31,7 @@ defmodule Cocktail.Builder.String do @spec build(Schedule.t()) :: String.t() def build(%Schedule{recurrence_rules: recurrence_rules}) do recurrence_rules - |> Enum.map(&build_rule/1) - |> Enum.join(" / ") + |> Enum.map_join(" / ", &build_rule/1) end @doc false diff --git a/mix.exs b/mix.exs index db04647..fd411d5 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Cocktail.Mixfile do use Mix.Project - @version "0.10.1" + @version "0.10.2" def project do [ @@ -39,7 +39,7 @@ defmodule Cocktail.Mixfile do defp package do [ files: ["lib", "mix.exs", "README.md", "LICENSE.md"], - maintainers: ["Chris Dosé"], + maintainers: ["Jesse Van Volkinburg", "Chris Dosé"], licenses: ["MIT"], links: %{ "GitHub" => "https://github.com/peek-travel/cocktail", @@ -51,11 +51,11 @@ defmodule Cocktail.Mixfile do defp docs do [ - main: "Cocktail.Schedule", + main: "readme", logo: "logo.png", source_ref: @version, source_url: "https://github.com/peek-travel/cocktail", - extras: ["README.md", "LICENSE.md"] + extras: ["README.md", "LICENSE.md", "CHANGELOG.md"] ] end diff --git a/mix.lock b/mix.lock index ad82061..9741a2d 100644 --- a/mix.lock +++ b/mix.lock @@ -1,27 +1,27 @@ %{ - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, - "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, + "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, + "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, - "credo": {:hex, :credo, "1.5.6", "e04cc0fdc236fefbb578e0c04bd01a471081616e741d386909e527ac146016c6", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4b52a3e558bd64e30de62a648518a5ea2b6e3e5d2b164ef5296244753fc7eb17"}, - "dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, + "dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"}, - "excoveralls": {:hex, :excoveralls, "0.14.1", "14140e4ef343f2af2de33d35268c77bc7983d7824cb945e6c2af54235bc2e61f", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4a588f9f8cf9dc140cc1f3d0ea4d849b2f76d5d8bee66b73c304bb3d3689c8b0"}, + "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, + "excoveralls": {:hex, :excoveralls, "0.15.1", "83c8cf7973dd9d1d853dce37a2fb98aaf29b564bf7d01866e409abf59dac2c0e", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f8416bd90c0082d56a2178cf46c837595a06575f70a5624f164a1ffe37de07e7"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"}, - "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, + "gettext": {:hex, :gettext, "0.20.0", "75ad71de05f2ef56991dbae224d35c68b098dd0e26918def5bb45591d5c8d429", [:mix], [], "hexpm", "1c03b177435e93a47441d7f681a7040bd2a816ece9e2666d1c9001035121eb3d"}, + "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, - "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, - "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, - "timex": {:hex, :timex, "3.7.5", "3eca56e23bfa4e0848f0b0a29a92fa20af251a975116c6d504966e8a90516dfd", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "a15608dca680f2ef663d71c95842c67f0af08a0f3b1d00e17bbd22872e2874e4"}, - "tzdata": {:hex, :tzdata, "1.1.0", "72f5babaa9390d0f131465c8702fa76da0919e37ba32baa90d93c583301a8359", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "18f453739b48d3dc5bcf0e8906d2dc112bb40baafe2c707596d89f3c8dd14034"}, + "timex": {:hex, :timex, "3.7.9", "790cdfc4acfce434e442f98c02ea6d84d0239073bfd668968f82ac63e9a6788d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "64691582e5bb87130f721fc709acfb70f24405833998fabf35be968984860ce1"}, + "tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, } diff --git a/test/cocktail/builder/string_test.exs b/test/cocktail/builder/string_test.exs index 86e61a9..6d71f6b 100644 --- a/test/cocktail/builder/string_test.exs +++ b/test/cocktail/builder/string_test.exs @@ -27,6 +27,30 @@ defmodule Cocktail.Builder.StringTest do assert string == "Weekly on Mondays" end + test "build schedules for remaining BYDAY options: Sunday, Tuesday, Thursday, Saturday" do + schedule = + ~N[2017-01-01 09:00:00] + |> Cocktail.schedule() + |> Schedule.add_recurrence_rule(:weekly, days: [:sunday, :tuesday, :thursday, :saturday]) + + assert Schedule.to_string(schedule) =~ "Sundays, Tuesdays, Thursdays and Saturdays" + end + + test "build schedules for remaining BYDAY options: Weekends and Weekdays" do + weekend_schedule = + ~N[2017-01-01 09:00:00] + |> Cocktail.schedule() + |> Schedule.add_recurrence_rule(:weekly, days: [:sunday, :saturday]) + + weekday_schedule = + ~N[2017-01-01 09:00:00] + |> Cocktail.schedule() + |> Schedule.add_recurrence_rule(:weekly, days: [:monday, :tuesday, :wednesday, :thursday, :friday]) + + assert Schedule.to_string(weekend_schedule) =~ "Weekends" + assert Schedule.to_string(weekday_schedule) =~ "Weekdays" + end + test "build a schedule with a BYHOUR option" do schedule = ~N[2017-01-01 09:00:00] diff --git a/test/cocktail/monthly_test.exs b/test/cocktail/monthly_test.exs index 89cbc89..bb1771a 100644 --- a/test/cocktail/monthly_test.exs +++ b/test/cocktail/monthly_test.exs @@ -5,14 +5,14 @@ defmodule Cocktail.MonthlyTest do import Cocktail.TestSupport.DateTimeSigil - @spec first_n_occurrences(%Cocktail.Schedule{}, integer()) :: term + @spec first_n_occurrences(Cocktail.Schedule.t(), integer()) :: term def first_n_occurrences(schedule, n \\ 20) do schedule |> Cocktail.Schedule.occurrences() |> Enum.take(n) end - @spec assert_icalendar_preserved(%Cocktail.Schedule{}) :: %Cocktail.Schedule{} + @spec assert_icalendar_preserved(Cocktail.Schedule.t()) :: Cocktail.Schedule.t() defp assert_icalendar_preserved(schedule) do {:ok, preserved_schedule} = schedule From 230963f37cc8b588041dfc9884299935a6b562f2 Mon Sep 17 00:00:00 2001 From: Brian Berlin Date: Fri, 22 Sep 2023 16:25:51 -0500 Subject: [PATCH 2/2] Fix test failures because of times with microseconds (#299) --- .tool-versions | 4 ++-- lib/cocktail/builder/i_calendar.ex | 4 +++- lib/cocktail/schedule_state.ex | 5 +++-- lib/cocktail/util.ex | 22 ++++++++++++++++++++++ lib/cocktail/validation/day_of_month.ex | 6 ++---- lib/cocktail/validation/interval.ex | 5 +++-- lib/cocktail/validation/schedule_lock.ex | 5 +++-- lib/cocktail/validation/shift.ex | 4 ++-- 8 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.tool-versions b/.tool-versions index 0b827a9..532f92b 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -elixir 1.12.1-otp-24 -erlang 24.0.2 +elixir 1.14.5-otp-25 +erlang 25.3.2 diff --git a/lib/cocktail/builder/i_calendar.ex b/lib/cocktail/builder/i_calendar.ex index 35cf3be..41189bf 100644 --- a/lib/cocktail/builder/i_calendar.ex +++ b/lib/cocktail/builder/i_calendar.ex @@ -5,6 +5,8 @@ defmodule Cocktail.Builder.ICalendar do TODO: write long description """ + import Cocktail.Util + alias Cocktail.{Rule, Schedule, Validation} alias Cocktail.Validation.{Day, DayOfMonth, HourOfDay, Interval, MinuteOfHour, SecondOfMinute, TimeOfDay, TimeRange} @@ -106,7 +108,7 @@ defmodule Cocktail.Builder.ICalendar do defp build_end_time(%Schedule{start_time: start_time, duration: duration}) do start_time - |> Timex.shift(seconds: duration) + |> shift_time(seconds: duration) |> build_time("DTEND") end diff --git a/lib/cocktail/schedule_state.ex b/lib/cocktail/schedule_state.ex index 0d257ff..492371a 100644 --- a/lib/cocktail/schedule_state.ex +++ b/lib/cocktail/schedule_state.ex @@ -2,6 +2,7 @@ defmodule Cocktail.ScheduleState do @moduledoc false alias Cocktail.{RuleState, Schedule, Span} + import Cocktail.Util @type t :: %__MODULE__{ recurrence_rules: [RuleState.t()], @@ -114,7 +115,7 @@ defmodule Cocktail.ScheduleState do | recurrence_rules: rules, recurrence_times: times, exception_times: exceptions, - current_time: Timex.shift(time, seconds: 1) + current_time: shift_time(time, seconds: 1) } {occurrence, new_state} @@ -122,7 +123,7 @@ defmodule Cocktail.ScheduleState do @spec span_or_time(Cocktail.time() | nil, pos_integer | nil) :: Cocktail.occurrence() defp span_or_time(time, nil), do: time - defp span_or_time(time, duration), do: Span.new(time, Timex.shift(time, seconds: duration)) + defp span_or_time(time, duration), do: Span.new(time, shift_time(time, seconds: duration)) @spec min_time_for_rules([RuleState.t()]) :: Cocktail.time() | nil defp min_time_for_rules([]), do: nil diff --git a/lib/cocktail/util.ex b/lib/cocktail/util.ex index 637e86b..21a85f5 100644 --- a/lib/cocktail/util.ex +++ b/lib/cocktail/util.ex @@ -3,4 +3,26 @@ defmodule Cocktail.Util do def next_gte([], _), do: nil def next_gte([x | rest], search), do: if(x >= search, do: x, else: next_gte(rest, search)) + + def beginning_of_day(time) do + time + |> Timex.beginning_of_day() + |> no_ms() + end + + def beginning_of_month(time) do + time + |> Timex.beginning_of_month() + |> no_ms() + end + + def shift_time(datetime, opts) do + datetime + |> Timex.shift(opts) + |> no_ms() + end + + def no_ms(time) do + Map.put(time, :microsecond, {0, 0}) + end end diff --git a/lib/cocktail/validation/day_of_month.ex b/lib/cocktail/validation/day_of_month.ex index acbaf8f..8c2d78a 100644 --- a/lib/cocktail/validation/day_of_month.ex +++ b/lib/cocktail/validation/day_of_month.ex @@ -2,7 +2,7 @@ defmodule Cocktail.Validation.DayOfMonth do @moduledoc false import Cocktail.Validation.Shift - import Cocktail.Util, only: [next_gte: 2] + import Cocktail.Util # assumed that DST can not "take" more than 4 hours between any 2 consecutive days @min_dst_resultant_hours 20 @@ -28,9 +28,7 @@ defmodule Cocktail.Validation.DayOfMonth do case next_gte(normalized_days, current_day_of_month) do # go to next month nil -> - next_month_time = - time - |> Timex.shift(months: 1) + next_month_time = shift_time(time, months: 1) next_month_normalized_days = Enum.map(days, &normalize_day_of_month(&1, next_month_time)) next_month_earliest_day = Timex.set(next_month_time, day: hd(Enum.sort(next_month_normalized_days))) diff --git a/lib/cocktail/validation/interval.ex b/lib/cocktail/validation/interval.ex index 17a8c91..4f5ca43 100644 --- a/lib/cocktail/validation/interval.ex +++ b/lib/cocktail/validation/interval.ex @@ -3,6 +3,7 @@ defmodule Cocktail.Validation.Interval do import Integer, only: [mod: 2, floor_div: 2] import Cocktail.Validation.Shift + import Cocktail.Util @typep iso_week :: {Timex.Types.year(), Timex.Types.weeknum()} @@ -20,8 +21,8 @@ defmodule Cocktail.Validation.Interval do def next_time(%__MODULE__{type: :monthly, interval: interval}, time, start_time) do start_time - |> Timex.beginning_of_month() - |> Timex.diff(Timex.beginning_of_month(time), :months) + |> beginning_of_month() + |> Timex.diff(beginning_of_month(time), :months) |> mod(interval) |> shift_by(:months, time) end diff --git a/lib/cocktail/validation/schedule_lock.ex b/lib/cocktail/validation/schedule_lock.ex index 72fd331..5769e63 100644 --- a/lib/cocktail/validation/schedule_lock.ex +++ b/lib/cocktail/validation/schedule_lock.ex @@ -3,6 +3,7 @@ defmodule Cocktail.Validation.ScheduleLock do import Integer, only: [mod: 2] import Cocktail.Validation.Shift + import Cocktail.Util @type lock :: :second | :minute | :hour | :wday | :mday @@ -34,7 +35,7 @@ defmodule Cocktail.Validation.ScheduleLock do def next_time(%__MODULE__{type: :mday}, time, start_time) do if start_time.day > Calendar.ISO.days_in_month(time.year, time.month) do - next_time(%__MODULE__{type: :mday}, Timex.shift(time, months: 1), start_time) + next_time(%__MODULE__{type: :mday}, shift_time(time, months: 1), start_time) else next_mday_time(%__MODULE__{type: :mday}, time, start_time) end @@ -56,7 +57,7 @@ defmodule Cocktail.Validation.ScheduleLock do |> Timex.diff(time, :days) start_time_day_of_month -> - next_month_date = Timex.shift(time, months: 1) + next_month_date = shift_time(time, months: 1) # Timex.set already handle the marginal case like setting a day of month more than the month contains next_month_date |> Timex.set(day: start_time_day_of_month) diff --git a/lib/cocktail/validation/shift.ex b/lib/cocktail/validation/shift.ex index 3e163f8..1c5c766 100644 --- a/lib/cocktail/validation/shift.ex +++ b/lib/cocktail/validation/shift.ex @@ -9,7 +9,7 @@ defmodule Cocktail.Validation.Shift do @typep option :: nil | :beginning_of_day | :beginning_of_hour | :beginning_of_minute - import Timex, only: [shift: 2, beginning_of_day: 1] + import Cocktail.Util @spec shift_by(integer, shift_type, Cocktail.time(), option) :: result def shift_by(amount, type, time, option \\ nil) @@ -18,7 +18,7 @@ defmodule Cocktail.Validation.Shift do def shift_by(amount, type, time, option) do new_time = time - |> shift("#{type}": amount) + |> shift_time("#{type}": amount) |> apply_option(option) {:change, new_time}