How to make integer into array of dates?

孤人 提交于 2020-01-04 09:03:39

问题


If a user creates a challenge with days_challenge: 5 & committed: ["mon", "tue", "wed", "thu", "fri"] then how can we create an array of dates from date_started: "2016-04-20" until the last day of the challenge using a model method called dates_challenged?

create_table "challenges", force: true do |t|
  t.string   "action"
  t.date     "date_started"
  t.text     "committed",       default: "---\n- sun\n- mon\n- tue\n- wed\n- thu\n- fri\n- sat\n"
  t.integer  "days_challenged"
end

The array would look something like this: ["2016-04-20", "2016-04-21", "2016-04-22", "2016-04-25", "2016-04-26"]

class Challenge < ActiveRecord::Base
  serialize :committed, Array

  def dates_challenged
    # Not sure if a model method is enough or if I'd have to migrate a new column
  end

  def committed_wdays
    committed.map do |day|    
      Date::ABBR_DAYNAMES.index(day.titleize)
    end
  end

  def days_left_challenged
    def days_done_challenged
      ((date_started.to_date)..Date.yesterday).count do |date| 
        committed_wdays.include? date.wday
      end
    end  
    if self.days_done_challenged >= self.days_challenged
      0
    else
      self.days_challenged - ((date_started.to_date)..Date.yesterday).count do |date| 
        committed_wdays.include? date.wday
      end
    end
  end
end

To clarify, I'm trying to make a model method so I could do @challenge.dates_challenged in a view where I can then iterate over the array of dates.


回答1:


This is what I came up with - there are still some issues - I think it will blow up if committed is empty, but it's nice and concise:

def dates_challenged
  date = date_started-1
  days_challenge.times.map { date = find_next(date) }
end

private
def find_next(date)
  break if committed.include? Date::ABBR_DAYNAMES[date.wday].downcase while date = date.next
  date
end



回答2:


Get the start date and end date - then you can get a range of dates and or days between the start and the end

start_date = challenge.date.to_date
end_date   = another_challenge.date.to_date
(start_date..end_date).map(&:mday) # returns array of days of the month

see List Array of Days Between Two Dates for more information




回答3:


Simple and verbose: create a date object from your date string (Date.parse), and create an empty array to hold the dates that you are 'committing' to. The list of days of the week that are available is stored in an array, as above. Loop until the number of days we are committing to stored in the array is equal to how many days were requested, adding one day to each previous day. Dates added to the date_committed array are checked against the valid days of week array (days_committed).

require 'date'

days_challenge = 5
days_committed = ["mon", "tue", "wed", "thu", "fri"] 
date_started = "2016-04-20"
date_committed = []
date_started_parsed = Date.parse(date_started)

while (date_committed.size < days_challenge)
  date_dow = date_started_parsed.strftime('%a').downcase
  if (days_committed.include?(date_dow))
    date_committed << date_started_parsed.strftime('%F')
  end # if
  date_started_parsed = date_started_parsed + 1
end # while

puts date_committed.to_s

Returns the correct dates based on valid days of the week.

["2016-04-20", "2016-04-21", "2016-04-22", "2016-04-25", "2016-04-26"]



回答4:


committed = ["mon", "tue", "wed", "thu", "fri"]
days = committed.dup

count = 0
dates = []

while days.present?
    count += 1
    weekday = (date + count).strftime('%a').downcase
    if days.include? weekday
        dates << (date + count.days).strftime('%Y-%m-%d')
        days.delete(weekday)
    end
end

puts dates # => ["2016-04-21", "2016-04-22", "2016-04-25", "2016-04-26", "2016-04-27"] 

Previuos answer

Assuming you are in Rails environment:

days_challenge = 5
date           = DateTime.parse("2016-04-20")

(1..days_challenge).map {|n| (date + n.days).strftime('%Y-%m-%d') }

# Outputs
["2016-04-21", "2016-04-22", "2016-04-23", "2016-04-24", "2016-04-25"]


来源:https://stackoverflow.com/questions/36755716/how-to-make-integer-into-array-of-dates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!