From 258052b852398f9239633a891d14b16325f4ec6e Mon Sep 17 00:00:00 2001 From: haoxilu Date: Fri, 24 Feb 2017 09:05:43 +0800 Subject: [PATCH 1/2] :sparkles: rails timezone support --- lib/crono/cli.rb | 4 ++-- lib/crono/job.rb | 10 +++++----- lib/crono/period.rb | 8 ++++---- lib/crono/time_of_day.rb | 4 ++-- spec/job_spec.rb | 4 ++-- spec/period_spec.rb | 34 +++++++++++++++++----------------- spec/spec_helper.rb | 2 ++ 7 files changed, 34 insertions(+), 32 deletions(-) diff --git a/lib/crono/cli.rb b/lib/crono/cli.rb index c4835b5..bbec31e 100644 --- a/lib/crono/cli.rb +++ b/lib/crono/cli.rb @@ -22,7 +22,7 @@ module Crono parse_options(ARGV) parse_command(ARGV) - setup_log + setup_log write_pid unless config.daemonize load_rails @@ -120,7 +120,7 @@ module Crono def start_working_loop loop do next_time, jobs = Crono.scheduler.next_jobs - sleep(next_time - Time.now) if next_time > Time.now + sleep(next_time - Time.zone.now) if next_time > Time.zone.now jobs.each(&:perform) end end diff --git a/lib/crono/job.rb b/lib/crono/job.rb index 70413b4..be8ee1a 100644 --- a/lib/crono/job.rb +++ b/lib/crono/job.rb @@ -12,7 +12,7 @@ module Crono def initialize(performer, period, job_args, job_options = nil) self.execution_interval = 0.minutes self.performer, self.period = performer, period - self.job_args = JSON.generate(job_args) + self.job_args = JSON.generate(job_args) self.job_log = StringIO.new self.job_logger = Logger.new(job_log) self.job_options = job_options || {} @@ -22,7 +22,7 @@ module Crono def next return next_performed_at if next_performed_at.future? - Time.now + Time.zone.now end def description @@ -37,7 +37,7 @@ module Crono return Thread.new {} if perform_before_interval? log "Perform #{performer}" - self.last_performed_at = Time.now + self.last_performed_at = Time.zone.now self.next_performed_at = period.next(since: last_performed_at) Thread.new { perform_job } @@ -86,7 +86,7 @@ module Crono end def handle_job_fail(exception) - finished_time_sec = format('%.2f', Time.now - last_performed_at) + finished_time_sec = format('%.2f', Time.zone.now - last_performed_at) self.healthy = false log_error "Finished #{performer} in #{finished_time_sec} seconds"\ " with error: #{exception.message}" @@ -94,7 +94,7 @@ module Crono end def handle_job_success - finished_time_sec = format('%.2f', Time.now - last_performed_at) + finished_time_sec = format('%.2f', Time.zone.now - last_performed_at) self.healthy = true log "Finished #{performer} in #{finished_time_sec} seconds" end diff --git a/lib/crono/period.rb b/lib/crono/period.rb index 5bd0893..802145e 100644 --- a/lib/crono/period.rb +++ b/lib/crono/period.rb @@ -27,7 +27,7 @@ module Crono @next = @next.beginning_of_week.advance(days: @on) if @on @next = @next.change(time_atts) return @next if @next.future? - Time.now + Time.zone.now end def description @@ -47,8 +47,8 @@ module Crono end def initial_day - return Time.now unless @on - day = Time.now.beginning_of_week.advance(days: @on) + return Time.zone.now unless @on + day = Time.zone.now.beginning_of_week.advance(days: @on) day = day.change(time_atts) return day if day.future? @period.from_now.beginning_of_week.advance(days: @on) @@ -68,7 +68,7 @@ module Crono case at when String - time = Time.parse(at) + time = Time.zone.parse(at) return time.hour, time.min when Hash return at[:hour], at[:min] diff --git a/lib/crono/time_of_day.rb b/lib/crono/time_of_day.rb index 63c541d..3da916d 100644 --- a/lib/crono/time_of_day.rb +++ b/lib/crono/time_of_day.rb @@ -8,8 +8,8 @@ module Crono def self.parse(value) time = case value - when String then Time.parse(value).utc - when Hash then Time.now.change(value).utc + when String then Time.zone.parse(value).utc + when Hash then Time.zone.now.change(value).utc when Time then value.utc else fail "Unknown TimeOfDay format: #{value.inspect}" diff --git a/spec/job_spec.rb b/spec/job_spec.rb index 7860fb0..158f7ee 100644 --- a/spec/job_spec.rb +++ b/spec/job_spec.rb @@ -98,7 +98,7 @@ describe Crono::Job do end it 'should update saved job' do - job.last_performed_at = Time.now + job.last_performed_at = Time.zone.now job.healthy = true job.job_args = JSON.generate([{some: 'data'}]) job.save @@ -134,7 +134,7 @@ describe Crono::Job do describe '#load' do before do - @saved_last_performed_at = job.last_performed_at = Time.now + @saved_last_performed_at = job.last_performed_at = Time.zone.now job.save end diff --git a/spec/period_spec.rb b/spec/period_spec.rb index f9ec005..4480851 100644 --- a/spec/period_spec.rb +++ b/spec/period_spec.rb @@ -27,23 +27,23 @@ describe Crono::Period do it "should return a 'on' day" do @period = Crono::Period.new(1.week, on: :thursday, at: '15:30') - current_week = Time.now.beginning_of_week + current_week = Time.zone.now.beginning_of_week last_run_time = current_week.advance(days: 1) # last run on the tuesday - next_run_at = Time.now.next_week.advance(days: 3) + next_run_at = Time.zone.now.next_week.advance(days: 3) .change(hour: 15, min: 30) expect(@period.next(since: last_run_time)).to be_eql(next_run_at) end it "should return a next week day 'on'" do @period = Crono::Period.new(1.week, on: :thursday) - Timecop.freeze(Time.now.beginning_of_week.advance(days: 4)) do - expect(@period.next).to be_eql(Time.now.next_week.advance(days: 3)) + Timecop.freeze(Time.zone.now.beginning_of_week.advance(days: 4)) do + expect(@period.next).to be_eql(Time.zone.now.next_week.advance(days: 3)) end end it 'should return a current week day on the first run if not too late' do @period = Crono::Period.new(7.days, on: :tuesday) - beginning_of_the_week = Time.now.beginning_of_week + beginning_of_the_week = Time.zone.now.beginning_of_week tuesday = beginning_of_the_week.advance(days: 1) Timecop.freeze(beginning_of_the_week) do expect(@period.next).to be_eql(tuesday) @@ -52,19 +52,19 @@ describe Crono::Period do it 'should return today on the first run if not too late' do @period = Crono::Period.new(1.week, on: :sunday, at: '22:00') - Timecop.freeze(Time.now.beginning_of_week.advance(days: 6) + Timecop.freeze(Time.zone.now.beginning_of_week.advance(days: 6) .change(hour: 21, min: 0)) do expect(@period.next).to be_eql( - Time.now.beginning_of_week.advance(days: 6).change(hour: 22, min: 0) + Time.zone.now.beginning_of_week.advance(days: 6).change(hour: 22, min: 0) ) end end end context 'in daily basis' do - it "should return Time.now if the next time in past" do + it "should return Time.zone.now if the next time in past" do @period = Crono::Period.new(1.day, at: '06:00') - expect(@period.next(since: 2.days.ago).to_s).to be_eql(Time.now.to_s) + expect(@period.next(since: 2.days.ago).to_s).to be_eql(Time.zone.now.to_s) end it 'should return time 2 days from now' do @@ -107,33 +107,33 @@ describe Crono::Period do time = 10.minutes.from_now at = { hour: time.hour, min: time.min } @period = Crono::Period.new(2.days, at: at) - expect(@period.next.utc.to_s).to be_eql(Time.now.change(at).utc.to_s) + expect(@period.next.utc.to_s).to be_eql(Time.zone.now.change(at).utc.to_s) end end context 'in hourly basis' do it 'should return next hour minutes if current hour minutes passed' do - Timecop.freeze(Time.now.beginning_of_hour.advance(minutes: 20)) do + Timecop.freeze(Time.zone.now.beginning_of_hour.advance(minutes: 20)) do @period = Crono::Period.new(1.hour, at: { min: 15 }) expect(@period.next.utc.to_s).to be_eql 1.hour.from_now.beginning_of_hour.advance(minutes: 15).utc.to_s end end it 'should return current hour minutes if current hour minutes not passed yet' do - Timecop.freeze(Time.now.beginning_of_hour.advance(minutes: 10)) do + Timecop.freeze(Time.zone.now.beginning_of_hour.advance(minutes: 10)) do @period = Crono::Period.new(1.hour, at: { min: 15 }) - expect(@period.next.utc.to_s).to be_eql Time.now.beginning_of_hour.advance(minutes: 15).utc.to_s + expect(@period.next.utc.to_s).to be_eql Time.zone.now.beginning_of_hour.advance(minutes: 15).utc.to_s end end it 'should return next hour minutes within the given interval' do - Timecop.freeze(Time.now.change(hour: 16, min: 10)) do + Timecop.freeze(Time.zone.now.change(hour: 16, min: 10)) do @period = Crono::Period.new(1.hour, at: { min: 15 }, within: '08:00-16:00') - expect(@period.next.utc.to_s).to be_eql Time.now.tomorrow.change(hour: 8, min: 15).utc.to_s + expect(@period.next.utc.to_s).to be_eql Time.zone.now.tomorrow.change(hour: 8, min: 15).utc.to_s end - Timecop.freeze(Time.now.change(hour: 16, min: 10)) do + Timecop.freeze(Time.zone.now.change(hour: 16, min: 10)) do @period = Crono::Period.new(1.hour, at: { min: 15 }, within: '23:00-07:00') - expect(@period.next.utc.to_s).to be_eql Time.now.change(hour: 23, min: 15).utc.to_s + expect(@period.next.utc.to_s).to be_eql Time.zone.now.change(hour: 23, min: 15).utc.to_s end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c528a41..0449611 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,8 @@ require 'byebug' require 'crono' require 'generators/crono/install/templates/migrations/create_crono_jobs.rb' +Time.zone_default = Time.find_zone("UTC") + ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: 'file::memory:?cache=shared' From d72a2d2b07c7f7c5dd0a739a95adce14d879274c Mon Sep 17 00:00:00 2001 From: haoxilu Date: Tue, 7 Mar 2017 23:02:42 +0800 Subject: [PATCH 2/2] write some annotation --- spec/spec_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0449611..388a918 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,8 @@ require 'byebug' require 'crono' require 'generators/crono/install/templates/migrations/create_crono_jobs.rb' +# setting default time zone +# In Rails project, Time.zone_default equals "UTC" Time.zone_default = Time.find_zone("UTC") ActiveRecord::Base.establish_connection(