Создайте список дат

Допустим, я использую Timex следующим образом:

use Timex
Interval.new(from: ~D[2016-03-03], until: [days: 3])
%Elixir.Timex.Interval{from: ~N[2016-03-03 00:00:00], left_open: false, right_open: true, step: [days: 1], until: ~N[2016-03-06 00:00:00]}

Я хочу сгенерировать список дат, с разницей в один день. Как мне перейти от этого к списку?

2 ответа

Решение

Почему вы используете сторонние библиотеки, такие как Timex за такую ​​простую вещь?

Enum.map(0..3, &Date.add(~D[2016-03-03], &1))
#⇒ [~D[2016-03-03], ~D[2016-03-04], ~D[2016-03-05], ~D[2016-03-06]]

Как перейти от [интервала] к списку?

В исходном коде для Timex.IntervalЕсть несколько примеров того, что вы можете сделать. Вот модифицированная версия одного из этих примеров:

  def days_as_strings(interval) do
    interval
    |> Interval.with_step([days: 1]) 
    |> Enum.map(&Timex.format!(&1, "%Y-%m-%d", :strftime))
  end

В оболочке:

~/elixir_programs/http$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> use Timex
Timex.Timezone

iex(2)> interval = Interval.new(from: ~D[2016-03-03], until: [days: 3])
%Timex.Interval{
  from: ~N[2016-03-03 00:00:00],
  left_open: false,
  right_open: true,
  step: [days: 1],
  until: ~N[2016-03-06 00:00:00]
}

iex(3)> MyTime.days_as_strings(interval)
["2016-03-03", "2016-03-04", "2016-03-05"]

iex(4)> 

Заметить, что Enum.map() называется последним шагом в конвейере, поэтому, что бы ни возвращала предыдущая строка, это Enumerable. Ну, модуль Enum также определяет функцию Enum.to_list()так что давайте попробуем это вместо Enum.map():

  def days_as_dates(interval) do
    interval
    |> Interval.with_step([days: 1])
    |> Enum.to_list()
  end

В оболочке:

~/elixir_programs/http$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> use Timex
Timex.Timezone

iex(2)> interval = Interval.new(from: ~D[2016-03-03], until: [days: 3])
%Timex.Interval{
  from: ~N[2016-03-03 00:00:00],
  left_open: false,
  right_open: true,
  step: [days: 1],
  until: ~N[2016-03-06 00:00:00]
}

iex(3)> MyTime.days_as_dates(interval)
[~N[2016-03-03 00:00:00], ~N[2016-03-04 00:00:00],
 ~N[2016-03-05 00:00:00]]

iex(4)> 

Вывод показывает, что элементы перечисляемого NaiveDateTimeс датой и временем без информации о часовом поясе.

NaiveDateTime модуль определяет функцию to_date/1так что мы можем отобразить to_date/1 на элементы интервала, чтобы получить Date"S:

  def days_as_dates(interval) do
    interval
    |> Interval.with_step([days: 1])
    |> Enum.map(&NaiveDateTime.to_date/1)
  end

В оболочке:

~/elixir_programs/http$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Compiling 1 file (.ex)
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> use Timex
Timex.Timezone 

iex(2)> interval = Interval.new(from: ~D[2016-03-03], until: [days: 3])
%Timex.Interval{
  from: ~N[2016-03-03 00:00:00],
  left_open: false,
  right_open: true,
  step: [days: 1],
  until: ~N[2016-03-06 00:00:00]
}

iex(3)> MyTime.days_as_dates(interval)                    
[~D[2016-03-03], ~D[2016-03-04], ~D[2016-03-05]]

iex(4)> 

И, оказывается, шаг по умолчанию [days: 1] когда вы перебираете интервал, вы можете просто написать:

  def days_as_dates(interval) do
    for ndt <- interval, do: NaiveDateTime.to_date(ndt)
  end
Другие вопросы по тегам