Last active
August 29, 2015 14:03
-
-
Save agius/7d630e21e18a6b6dc5cb to your computer and use it in GitHub Desktop.
Output timezone select in Rails with some data attrs for JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var d = new Date(); | |
var tz_offset = d.getTimezoneOffset(); // seconds, not ms, because Javascript | |
var tz_select = $('#tz-select'); | |
var abbr = tz_select.find("option[data-offset='" + tz_offset + "']").data('abbreviation'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Usage | |
# validates :event_time, time_is: { after_now: true } | |
# validates :last_event, time_is: { before_now: true } | |
# validates :event_time, time_is: { before: Time.zone.now - 5.days } | |
# validates :event_time, time_is: { after: Time.zone.now + 5.days } | |
class TimeIsValidator < ActiveModel::EachValidator | |
# ignore time differences smaller than one second | |
def compare(time_1, time_2) | |
return -1 if time_1 - time_2 < -1 | |
return 1 if time_1 - time_2 > 1 | |
return 0 | |
end | |
def validate_each(record, attribute, value) | |
return unless value.present? | |
raise ArgumentError.new("No options specified for time_is: on #{record.class.name}") unless options.is_a?(Hash) | |
# use integers; otherwise Time tracks to the nanosecond, which can easily mess up tests | |
now = Time.zone.now | |
time_value = value | |
if options[:before_now] && time_value - now >= 1 | |
record.errors[attribute] << "is not before now" | |
end | |
if options[:after_now] && time_value - now <= 1 | |
record.errors[attribute] << "is not afer now" | |
end | |
if options[:now_or_earlier] && time_value - now >= 1 | |
record.errors[attribute] << "is later than now" | |
end | |
if options[:now_or_later] && time_value - now <= -1 | |
record.errors[attribute] << "is earlier than now" | |
end | |
if options[:before] | |
compare_to = options[:before] | |
compare_to = record.send(compare_to) if compare_to.is_a?(Symbol) | |
compare_to = compare_to.to_time | |
if time_value - compare_to >= -1 | |
record.errors[attribute] << "is not before #{options[:before]}" | |
end | |
end | |
if options[:at_or_before] | |
compare_to = options[:at_or_before] | |
compare_to = record.send(compare_to) if compare_to.is_a?(Symbol) | |
compare_to = compare_to.to_time | |
if time_value - compare_to <= 1 | |
record.errors[attribute] << "is not on or before #{options[:before]}" | |
end | |
end | |
if options[:after] | |
compare_to = options[:after] | |
compare_to = record.send(compare_to) if compare_to.is_a?(Symbol) | |
compare_to = compare_to.to_time | |
if time_value - compare_to <= 1 | |
record.errors[attribute] << "is not after #{options[:before]}" | |
end | |
end | |
if options[:at_or_after] | |
compare_to = options[:at_or_after] | |
compare_to = record.send(compare_to) if compare_to.is_a?(Symbol) | |
compare_to = compare_to.to_time | |
if time_value - compare_to >= -1 | |
record.errors[attribute] << "is not on or after #{options[:at_or_after]}" | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Usage | |
# expect(time_instance).to be_time(Time.zone.now) | |
# match times, but ignore differences smaller than one second. | |
# prevents race conditions in validation, expect() etc with times | |
# handy with TimeCop - https://github.com/travisjeffery/timecop | |
RSpec::Matchers.define :be_time do |expected| | |
match do |actual| | |
expected == actual || ((expected - actual) < 1 && (expected - actual) > -1) | |
end | |
failure_message do |actual| | |
format = '%b %-d, %Y %H:%M:%S %N %z' | |
"expected #{actual.strftime(format)} would be #{expected.strftime(format)}" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def time_zones_for_js(selected) | |
prev_offsets = [] | |
html = "" | |
time_zones = ActiveSupport::TimeZone.us_zones.reverse | |
time_zones.each do |zone| | |
next if prev_offsets.include?(zone.utc_offset) | |
next unless zone.to_s =~ /Time/ | |
html << "<option value='#{zone.name}' | |
data-abbreviation='#{zone.now.zone}' | |
data-offset='#{zone.tzinfo.period_for_utc(Time.now).utc_total_offset}' | |
{zone.name == selected ? 'selected=\'selected\'' : ''}>" | |
html << "(GMT#{zone.formatted_offset}) #{zone.tzinfo.friendly_identifier}" | |
html << "</option>" | |
prev_offsets << zone.utc_offset | |
end | |
html << "<option disabled='disabled'>--------------</option>" | |
ActiveSupport::TimeZone.all.each do |zone| | |
next if prev_offsets.include?(zone.name) | |
html << "<option value='#{zone.name}' | |
data-abbreviation='#{zone.now.zone}' | |
data-offset='#{zone.tzinfo.period_for_utc(Time.now).utc_total_offset}' | |
#{zone.to_s == selected ? 'selected=\'selected\'' : ''}>" | |
html << "(GMT#{zone.formatted_offset}) #{zone.tzinfo.friendly_identifier}" | |
html << "</option>" | |
prev_offsets << zone.utc_offset | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
👍