【问题标题】:Generate a list of dates生成日期列表
【发布时间】:2019-02-15 15:29:16
【问题描述】:

假设我正在使用 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]}

我想生成一个日期列表,相隔一天。我如何从这个到列表?

【问题讨论】:

    标签: elixir timex


    【解决方案1】:

    为什么要使用像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]]
    

    【讨论】:

    • Date.range(~D[2016-03-03], Date.add(~D[2016-03-03], 3)) |> Enum.to_list 也将起作用,并且可能更好地为未来的读者保留“间隔”指示的意图。
    【解决方案2】:

    如何从 [an Interval] 转到列表?

    Timex.Interval 的源代码中,有some examples 可以做的事情。以下是其中一个示例的修改版本:

      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)> 
    

    输出显示 Enumerable 的元素是NaiveDateTime,它们是没有时区信息的日期时间。

    NaiveDateTime模块定义了一个函数to_date/1,所以我们可以将to_date/1映射到Interval的元素上,得到Date的:

      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)> 
    

    而且,当您遍历 Interval 时,默认步长是 [days: 1],所以您可以只写:

      def days_as_dates(interval) do
        for ndt <- interval, do: NaiveDateTime.to_date(ndt)
      end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      相关资源
      最近更新 更多