Reputation: 19456
Let's say I'm using Timex as follows:
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]}
I want to generate a list of dates, one day apart. How do I go from this to a list?
Upvotes: 3
Views: 1476
Reputation: 48589
How do I go from [an Interval] to a list?
In the source code for Timex.Interval
, there are some examples of what you can do. Here's a modified version of one of those examples:
def days_as_strings(interval) do
interval
|> Interval.with_step([days: 1])
|> Enum.map(&Timex.format!(&1, "%Y-%m-%d", :strftime))
end
In the shell:
~/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)>
Notice that Enum.map()
is called as the last step in the pipeline, so whatever the previous line returned is an Enumerable. Well, the Enum module also defines the function Enum.to_list()
, so let's try that instead of Enum.map()
:
def days_as_dates(interval) do
interval
|> Interval.with_step([days: 1])
|> Enum.to_list()
end
In the shell:
~/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)>
The output shows that the elements of the Enumerable are NaiveDateTime
's, which are datetime's with no timezone info.
The NaiveDateTime
module defines a function to_date/1
, so we can map to_date/1
onto the Interval's elements to get Date
's:
def days_as_dates(interval) do
interval
|> Interval.with_step([days: 1])
|> Enum.map(&NaiveDateTime.to_date/1)
end
In the shell:
~/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)>
And, it turns out that the default step is [days: 1]
when you iterate over the Interval, so you can just write:
def days_as_dates(interval) do
for ndt <- interval, do: NaiveDateTime.to_date(ndt)
end
Upvotes: 1
Reputation: 120990
Why would you use 3rd party libraries like Timex
for such a simple thing?
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]]
Upvotes: 7