Current section
Files
Jump to
Current section
Files
lib/calendarize.ex
defmodule Calendarize do
@moduledoc """
A small utility that generates a calendar month array given a date.
"""
alias Date
alias Timex
@type build_options :: [week_start: Timex.Types.weekstart()]
@doc """
Generates a calendar month array given a date. Currently, `week_start` is the only option, and it can be any integer 1..7 or
any string accepted by [Timex.day_to_num()](https://hexdocs.pm/timex/Timex.html#day_to_num/1). If not specified, `week_start`
defaults to :sun
## Examples
iex> Calendarize.build(~D[2020-05-15])
[
[0, 0, 0, 0, 0, 1, 2],
[3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16],
[17, 18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29, 30],
[31, 0, 0, 0, 0, 0, 0]
]
iex> Calendarize.build(~D[2020-05-15], week_start: :mon)
[
[0, 0, 0, 0, 1, 2, 3],
[4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23, 24],
[25, 26, 27, 28, 29, 30, 31],
[0, 0, 0, 0, 0, 0, 0]
]
iex> Calendarize.build(Timex.now, week_start: :mon)
[
[0, 0, 0, 0, 1, 2, 3],
[4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23, 24],
[25, 26, 27, 28, 29, 30, 31],
[0, 0, 0, 0, 0, 0, 0]
]
"""
@spec build(DateTime.t() | Date.t(), build_options()) :: list()
def build(%dt{} = date, opts \\ []) when dt in [DateTime, Date] do
get_dates(date, Keyword.get(opts, :week_start, :sun))
end
defp get_dates(date, week_start) do
{:ok, first_day_of_month} = Date.new(date.year, date.month, 1)
end_day = Date.days_in_month(date)
start_day = Timex.days_to_beginning_of_week(first_day_of_month, week_start)
for week <- 1..6 do
for day <- 0..6 do
get_date(week, day, start_day, end_day)
end
end
end
defp get_date(week, day_in_week, start_day, end_day) do
day_in_month = (week - 1) * 7 + day_in_week
if day_in_month < start_day or day_in_month > end_day + start_day - 1 do
0
else
day_in_month - start_day + 1
end
end
end