2015-10-12 3 views
-2

У меня есть массив под названием «дата», который выглядит, как это ...рефакторинга массив в рубине

@dates = [ 
    {:month => 'apr', :start_date => '2015-04-01', :end_date => '2015-05-01'}, 
    {:month => 'may', :start_date => '2015-05-01', :end_date => '2015-06-01'}, 
    {:month => 'jun', :start_date => '2015-06-01', :end_date => '2015-07-01'}, 
    {:month => 'jul', :start_date => '2015-07-01', :end_date => '2015-08-01'}, 
    {:month => 'aug', :start_date => '2015-08-01', :end_date => '2015-09-01'}, 
    {:month => 'sep', :start_date => '2015-09-01', :end_date => '2015-10-01'}, 
    {:month => 'oct', :start_date => '2015-10-01', :end_date => '2015-11-01'}, 
    {:month => 'nov', :start_date => '2015-11-01', :end_date => '2015-12-01'}, 
    {:month => 'dec', :start_date => '2015-12-01', :end_date => '2016-01-01'}, 
    {:month => 'jan', :start_date => '2016-01-01', :end_date => '2016-02-01'}, 
    {:month => 'feb', :start_date => '2016-02-01', :end_date => '2016-03-01'}, 
    {:month => 'mar', :start_date => '2016-03-01', :end_date => '2016-04-01'} 
    ] 

Я хотел бы, чтобы реорганизовать это, но это за меня. Я пытался работать на что-то вроде этого, но заблудился в том, что даты января/февраля/марта будет в следующем календарном году ....

@months = I18n.t("date.abbr_month_names").compact.rotate(3).map(&:downcase) 

@dates = [] 
@[email protected]_with_index do |mon, x| 
    @dates << {:month => mon, :start_date => Date.parse(mon).beginning_of_month, :end_date => Date.parse(mon).end_of_month + 1} 
end 

это почти работает, но за последние три месяца в Следующий год. У меня есть чувство, что я могу что-то с индексом, но не могу обмануть его

любые идеи?

+1

Вы не указано, что желаемый результат. Хочешь оставшиеся месяцы через год? Или вам нужен другой ярлык, если он будет в следующем году «feb 2016»? – max

+0

Я не уверен, что вы ищете, но если вы предоставляете пример использования или контекста, я могу уточнить свой ответ. –

ответ

0

Вы можете увеличивать год каждый раз, когда вы нажмете января:

ycount = 0 
@months.each do |mon| 
    ycount +=1 if mon.downcase == "jan" 
    date = (Date.parse(mon) + ycount.to_i.year) 
    @dates << {:month => mon, :start_date => date.beginning_of_month, :end_date => date.end_of_month + 1} 
end 

@dates 
# => [{:month=>"apr", :start_date=>Wed, 01 Apr 2015, :end_date=>Fri, 01 May 2015}, {:month=>"may", :start_date=>Fri, 01 May 2015, :end_date=>Mon, 01 Jun 2015}, {:month=>"jun", :start_date=>Mon, 01 Jun 2015, :end_date=>Wed, 01 Jul 2015}, {:month=>"jul", :start_date=>Wed, 01 Jul 2015, :end_date=>Sat, 01 Aug 2015}, {:month=>"aug", :start_date=>Sat, 01 Aug 2015, :end_date=>Tue, 01 Sep 2015}, {:month=>"sep", :start_date=>Tue, 01 Sep 2015, :end_date=>Thu, 01 Oct 2015}, {:month=>"oct", :start_date=>Thu, 01 Oct 2015, :end_date=>Sun, 01 Nov 2015}, {:month=>"nov", :start_date=>Sun, 01 Nov 2015, :end_date=>Tue, 01 Dec 2015}, {:month=>"dec", :start_date=>Tue, 01 Dec 2015, :end_date=>Fri, 01 Jan 2016}, {:month=>"jan", :start_date=>Fri, 01 Jan 2016, :end_date=>Mon, 01 Feb 2016}, {:month=>"feb", :start_date=>Mon, 01 Feb 2016, :end_date=>Tue, 01 Mar 2016}, {:month=>"mar", :start_date=>Tue, 01 Mar 2016, :end_date=>Fri, 01 Apr 2016}] 
0

Использование I18n.l для локализации даты аббревиатуру вместо этого.

def format_months(start_date = Date.today, months = 12) 
    start_date = start_date.beginning_of_month 
    months.times.map do |m| 
    starts = start_date + m.months 
    { 
     mon: I18n.l(starts, format: '%b'), 
     start_date: starts, 
     end_date: starts.end_of_month 
    } 
    end 
end 

Вы не совсем заявили, что это вы пытаетесь сделать, но с использованием Date.parse(mon).end_of_month + 1, чтобы получить конечную дату, кажется, не имеет особого смысла, так как все мы можем согласиться, что через месяц заканчивается в последний день (28 -29-30-31st) не 1-го числа следующего месяца.

irb(main):004:0> pp format_months 
[{:mon=>"Oct", :start_date=>Thu, 01 Oct 2015, :end_date=>Sat, 31 Oct 2015}, 
{:mon=>"Nov", :start_date=>Sun, 01 Nov 2015, :end_date=>Mon, 30 Nov 2015}, 
{:mon=>"Dec", :start_date=>Tue, 01 Dec 2015, :end_date=>Thu, 31 Dec 2015}, 
{:mon=>"Jan", :start_date=>Fri, 01 Jan 2016, :end_date=>Sun, 31 Jan 2016}, 
{:mon=>"Feb", :start_date=>Mon, 01 Feb 2016, :end_date=>Mon, 29 Feb 2016}, 
{:mon=>"Mar", :start_date=>Tue, 01 Mar 2016, :end_date=>Thu, 31 Mar 2016}, 
{:mon=>"Apr", :start_date=>Fri, 01 Apr 2016, :end_date=>Sat, 30 Apr 2016}, 
{:mon=>"May", :start_date=>Sun, 01 May 2016, :end_date=>Tue, 31 May 2016}, 
{:mon=>"Jun", :start_date=>Wed, 01 Jun 2016, :end_date=>Thu, 30 Jun 2016}, 
{:mon=>"Jul", :start_date=>Fri, 01 Jul 2016, :end_date=>Sun, 31 Jul 2016}, 
{:mon=>"Aug", :start_date=>Mon, 01 Aug 2016, :end_date=>Wed, 31 Aug 2016}, 
{:mon=>"Sep", :start_date=>Thu, 01 Sep 2016, :end_date=>Fri, 30 Sep 2016}] 
0

Я бы использовал объект для построения массива хешей. Это легко поддерживать и модифицировать:

require 'date' 
class Month 

    attr_reader :date 

    def self.between(start, finish) 
    months = [] 
    month = new(start) 
    while month.start_date <= finish.to_date 
     months << month 
     month = new(month.date.next_month) 
    end 
    months 
    end 

    def self.month_hashs_between(start, finish) 
    between(start, finish).collect &:to_hash 
    end 

    def initialize(date) 
    @date = date.to_date 
    end 

    def month 
    date.strftime('%b').downcase 
    end 

    def start_date 
    @start_date ||= Date.new(date.year, date.month, 1) 
    end 

    def end_date 
    @end_date ||= start_date.next_month 
    end 

    def to_hash 
    { 
     month: month, 
     start_date: start_date.to_s, 
     end_date: end_date.to_s 
    } 
    end 

end 

start = Date.new(2015, 04, 01) 
finish = Date.new(2016, 03, 01) 

p Month.month_hashs_between start, finish 
0

Вы не предоставили пример вывода или то, что он используется для но то, что я обычно сделать, это создать простой объект значения. Мы также можем использовать объекты Ruby's Date и Range, чтобы выполнить большую часть тяжелого подъема.

require 'date' 

class DateRange 

    def self.import dates 
    dates.map do |d| 
     self.new Date.parse(d[:start_date]), Date.parse(d[:end_date]) 
    end 
    end 

    def initialize start, finish 
    @range = Range.new start, finish 
    end 

    def month 
    Date::MONTHNAMES[start.month] 
    end 

    def mon 
    month[0..2] 
    end 

    def include? date 
    @range.include? date 
    end 

    def start 
    @range.begin 
    end 

    def finish 
    @range.end 
    end 

    def to_s 
    "#<#{self.class.name} #{start.iso8601}..#{finish.iso8601}>" 
    end 

end 

Мы используем start и finish потому begin и end зарезервированные слова Ruby, Range может использовать их, поскольку она реализуется в C. Мы могли бы передать объект Range или использовать объект Range непосредственно, но это значение объект позволяет нам отображать только тот интерфейс, который мы хотим.

Я выставил метод include?, который может быть использован для проверки того, находится ли заданная дата между начальной и конечной точками, так как это то, что люди любят делать с диапазонами дат.

Кроме того, мы используем константу MONTHNAMES, определенную на Date, чтобы указать нам имя месяца или короткое имя, которое является только первыми тремя буквами месяца, если вы в этом заняты.

Этот код может использоваться как отправная точка для любого объекта значения в системе, удалять ненужные вещи, добавлять нужные материалы.

Кроме того, я включил метод import в класс, который будет считываться в вашем массиве @dates и возвращает коллекцию объектов DateRange.


Ссылки

Смежные вопросы