Skip to content

Commit

Permalink
Merge branch 'main' into fix_occurrences_on_dst_transition
Browse files Browse the repository at this point in the history
  • Loading branch information
dimakula authored Jan 3, 2024
2 parents 55c23b9 + 230963f commit c695275
Show file tree
Hide file tree
Showing 20 changed files with 148 additions and 94 deletions.
82 changes: 41 additions & 41 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 }}
Expand All @@ -32,28 +32,28 @@ 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 }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
- 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
Expand All @@ -77,28 +77,28 @@ 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 }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
- 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
Expand All @@ -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

Expand All @@ -128,28 +128,28 @@ 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 }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
- 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
Expand Down Expand Up @@ -177,28 +177,28 @@ 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 }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
- 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
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
elixir 1.12.1-otp-24
erlang 24.0.2
elixir 1.14.5-otp-25
erlang 25.3.2
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
3 changes: 0 additions & 3 deletions config/config.exs

This file was deleted.

1 change: 0 additions & 1 deletion config/dev.exs

This file was deleted.

1 change: 0 additions & 1 deletion config/docs.exs

This file was deleted.

1 change: 0 additions & 1 deletion config/test.exs

This file was deleted.

16 changes: 8 additions & 8 deletions lib/cocktail/builder/i_calendar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down Expand Up @@ -82,7 +84,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()
Expand All @@ -105,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

Expand Down Expand Up @@ -175,8 +178,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
Expand All @@ -186,8 +188,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
Expand Down Expand Up @@ -244,8 +245,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
Expand Down
3 changes: 1 addition & 2 deletions lib/cocktail/builder/string.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions lib/cocktail/schedule_state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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()],
Expand Down Expand Up @@ -114,15 +115,15 @@ 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}
end

@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
Expand Down
22 changes: 22 additions & 0 deletions lib/cocktail/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 2 additions & 4 deletions lib/cocktail/validation/day_of_month.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)))
Expand Down
5 changes: 3 additions & 2 deletions lib/cocktail/validation/interval.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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()}

Expand All @@ -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
Expand Down
Loading

0 comments on commit c695275

Please sign in to comment.