Module: GreenButtonData::Dst
- Includes:
- Utilities
- Included in:
- LocalTimeParameters, Parser::LocalTimeParameters
- Defined in:
- lib/green-button-data/dst.rb
Constant Summary collapse
- BITMASK_SECOND =
From ESPI XML schema:
- extension
-
Bit map encoded rule from which is calculated the start or
end time, within the current year, to which daylight savings time offset must be applied.
The rule encoding: Bits 0 - 11: seconds 0 - 3599 Bits 12 - 16: hours 0 - 23 Bits 17 - 19: day of the week 0 = not applicable, 1 - 7 (Monday = 1) Bits:20 - 24: day of the month 0 = not applicable, 1 - 31 Bits: 25 - 27: operator (detailed below) Bits: 28 - 31: month 1 - 12
Rule value of 0xFFFFFFFF means rule processing/DST correction is disabled.
The operators:
0: DST starts/ends on the Day of the Month 1: DST starts/ends on the Day of the Week that is on or after the Day of the Month 2: DST starts/ends on the first occurrence of the Day of the Week in a month 3: DST starts/ends on the second occurrence of the Day of the Week in a month 4: DST starts/ends on the third occurrence of the Day of the Week in a month 5: DST starts/ends on the forth occurrence of the Day of the Week in a month 6: DST starts/ends on the fifth occurrence of the Day of the Week in a month 7: DST starts/ends on the last occurrence of the Day of the Week in a month
An example: DST starts on third Friday in March at 1:45 AM. The rule… Seconds: 2700 Hours: 1 Day of Week: 5 Day of Month: 0 Operator: 4 Month: 3
0x00000fff- BITMASK_HOUR =
0x0001f000- BITMASK_DAY_OF_WEEK =
0x000e0000- BITMASK_DAY_OF_MONTH =
0x01f00000- BITMASK_DST_RULE =
0x0e000000- BITMASK_MONTH =
0xf0000000- BITSHIFT_HOUR =
12- BITSHIFT_DAY_OF_WEEK =
17- BITSHIFT_DAY_OF_MONTH =
20- BITSHIFT_DST_RULE =
25- BITSHIFT_MONTH =
28
Instance Method Summary collapse
- #byte_to_dst_datetime(byte, year = Time.now.year) ⇒ Object
- #dst_datetime(dst_rule, year, month, weekday, day, hour, seconds) ⇒ Object
- #validate_dst_rules(dst_rule, month, weekday, day, hour, seconds) ⇒ Object
Methods included from Utilities
#attributes_to_hash, #class_from_name, #epoch_to_time, #first_sunday_of, #last_weekday_of, #normalize_epoch, #nth_weekday_of, #parse_datetime, #weekday_offset
Instance Method Details
#byte_to_dst_datetime(byte, year = Time.now.year) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/green-button-data/dst.rb', line 51 def byte_to_dst_datetime(byte, year = Time.now.year) # Bits 0 - 11: seconds 0 - 3599 seconds = byte & BITMASK_SECOND # Bits 12 - 16: hours 0 - 23 hour = (byte & BITMASK_HOUR) >> BITSHIFT_HOUR # Bits 17 - 19: day of the week; 0 = NA, 1 - 7 (Monday = 1) weekday = (byte & BITMASK_DAY_OF_WEEK) >> BITSHIFT_DAY_OF_WEEK # Bits 20 - 24: day of the month; 0 = NA, 1 - 31 day = (byte & BITMASK_DAY_OF_MONTH) >> BITSHIFT_DAY_OF_MONTH # Bits 25 - 27: DST rule 0 - 7 dst_rule = (byte & BITMASK_DST_RULE) >> BITSHIFT_DST_RULE # Bits 28 - 31: month 1 - 12 month = (byte & BITMASK_MONTH) >> BITSHIFT_MONTH # Raise an error unless all the values are in valid range validate_dst_rules dst_rule, month, weekday, day, hour, seconds # In Ruby, Sunday = 0 not 7 weekday = weekday == 7 ? 0 : weekday # Add the hour and seconds component to the day dst_datetime dst_rule, year, month, weekday, day, hour, seconds end |
#dst_datetime(dst_rule, year, month, weekday, day, hour, seconds) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/green-button-data/dst.rb', line 80 def dst_datetime(dst_rule, year, month, weekday, day, hour, seconds) if dst_rule == 1 # Rule 1: DST starts/ends on Day of Week on or after the Day of Month day_of_month = DateTime.new year, month, day day_offset = if weekday >= day_of_month.wday weekday - day_of_month.wday else 7 + weekday - day_of_month.wday end day_of_month + day_offset elsif dst_rule.between?(2, 6) # Rule 2 - 6: DST starts/ends on Nth Day of Week in given month # Nth Day of Week (e.g. third Friday of July) nth_weekday_of year, month, weekday, dst_rule - 1 elsif dst_rule == 7 # Rule 7: DST starts/ends on last Day of Week in given month last_weekday_of year, month, weekday else # Rule 0: DST starts/ends on the Day of Month DateTime.new year, month, day end + Rational(hour * 3600 + seconds, 86400) end |
#validate_dst_rules(dst_rule, month, weekday, day, hour, seconds) ⇒ Object
104 105 106 107 108 109 |
# File 'lib/green-button-data/dst.rb', line 104 def validate_dst_rules(dst_rule, month, weekday, day, hour, seconds) seconds.between?(0, 3599) and hour.between?(0, 23) and weekday.between?(1, 7) and day.between?(0, 31) and dst_rule.between?(0, 7) and month.between?(1, 12) or raise RangeError, 'Invalid value range' end |