Module: Tztr
- Defined in:
- lib/tztr.rb,
lib/tztr/version.rb
Constant Summary collapse
- PATTERNS =
[ # ISO 8601 with Z or offset: 2026-04-03T12:34:56Z, 2026-04-03T12:34:56.123+00:00 /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})/, # ISO 8601 without timezone: 2026-04-03T12:34:56 /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?/, # Date space time with tz: 2026-04-03 12:34:56 UTC /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? ?(?:UTC|GMT|[A-Z]{2,4}|[+-]\d{4})/, # Date space time: 2026-04-03 12:34:56 /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?/, # Time with tz: 12:34:56 UTC, 12:34 PST /\b\d{1,2}:\d{2}(?::\d{2}(?:\.\d+)?)? ?(?:UTC|GMT|[A-Z]{2,4}|[+-]\d{4})\b/, # Time with offset: 12:34:56+00:00 /\b\d{1,2}:\d{2}(?::\d{2}(?:\.\d+)?)?[+-]\d{2}:?\d{2}\b/, # Bare time: 12:34:56, 12:34 /\b\d{1,2}:\d{2}(?::\d{2}(?:\.\d+)?)?\b/, ].freeze
- TIMEZONE_ALIASES =
{ # UTC 'utc' => 'UTC', 'gmt' => 'UTC', 'z' => 'UTC', # US Eastern 'est' => 'America/New_York', 'edt' => 'America/New_York', 'et' => 'America/New_York', 'eastern' => 'America/New_York', # US Central 'cst' => 'America/Chicago', 'cdt' => 'America/Chicago', 'ct' => 'America/Chicago', 'central' => 'America/Chicago', # US Mountain 'mst' => 'America/Denver', 'mdt' => 'America/Denver', 'mt' => 'America/Denver', 'mountain' => 'America/Denver', # US Pacific 'pst' => 'America/Los_Angeles', 'pdt' => 'America/Los_Angeles', 'pt' => 'America/Los_Angeles', 'pacific' => 'America/Los_Angeles', # US Other 'hst' => 'Pacific/Honolulu', 'akst' => 'America/Anchorage', 'akdt' => 'America/Anchorage', # Europe 'cet' => 'Europe/Berlin', 'cest' => 'Europe/Berlin', 'gmt' => 'Europe/London', 'bst' => 'Europe/London', 'ist' => 'Asia/Kolkata', # Asia/Pacific 'jst' => 'Asia/Tokyo', 'kst' => 'Asia/Seoul', 'cst_china' => 'Asia/Shanghai', 'hkt' => 'Asia/Hong_Kong', 'aest' => 'Australia/Sydney', 'aedt' => 'Australia/Sydney', 'nzst' => 'Pacific/Auckland', 'nzdt' => 'Pacific/Auckland', # Cities 'sf' => 'America/Los_Angeles', 'la' => 'America/Los_Angeles', 'seattle' => 'America/Los_Angeles', 'denver' => 'America/Denver', 'chicago' => 'America/Chicago', 'nyc' => 'America/New_York', 'boston' => 'America/New_York', 'miami' => 'America/New_York', 'london' => 'Europe/London', 'paris' => 'Europe/Paris', 'berlin' => 'Europe/Berlin', 'amsterdam' => 'Europe/Amsterdam', 'tokyo' => 'Asia/Tokyo', 'sydney' => 'Australia/Sydney', 'mumbai' => 'Asia/Kolkata', 'delhi' => 'Asia/Kolkata', 'shanghai' => 'Asia/Shanghai', 'beijing' => 'Asia/Shanghai', 'hong_kong' => 'Asia/Hong_Kong', 'hongkong' => 'Asia/Hong_Kong', 'singapore' => 'Asia/Singapore', 'seoul' => 'Asia/Seoul', 'honolulu' => 'Pacific/Honolulu', 'hawaii' => 'Pacific/Honolulu', 'anchorage' => 'America/Anchorage', 'alaska' => 'America/Anchorage', 'toronto' => 'America/Toronto', 'vancouver' => 'America/Vancouver', 'auckland' => 'Pacific/Auckland', 'dubai' => 'Asia/Dubai', 'sao_paulo' => 'America/Sao_Paulo', }.freeze
- VERSION =
"0.1.0"
Class Method Summary collapse
- .format_time(time, fmt, original) ⇒ Object
- .has_timezone?(str) ⇒ Boolean
- .parse(str, from: nil, to: 'UTC') ⇒ Object
- .resolve_tz(input) ⇒ Object
- .translate(line, to: 'UTC', from: nil, format: nil) ⇒ Object
Class Method Details
.format_time(time, fmt, original) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/tztr.rb', line 131 def format_time(time, fmt, original) case fmt when :short then return time.strftime('%Y-%m-%d %H:%M') when :time then return time.strftime('%H:%M:%S') when :iso then return time.strftime('%Y-%m-%d %H:%M:%S') end # Preserve input format tz = time.utc_offset == 0 ? 'Z' : time.strftime('%:z') case original when /^\d{4}-\d{2}-\d{2}T/ has_frac = original.match?(/T\d{2}:\d{2}:\d{2}\.\d+/) base = has_frac ? time.strftime('%Y-%m-%dT%H:%M:%S.%L') : time.strftime('%Y-%m-%dT%H:%M:%S') base + tz when /^\d{4}-\d{2}-\d{2} / has_frac = original.match?(/ \d{2}:\d{2}:\d{2}\.\d+/) base = has_frac ? time.strftime('%Y-%m-%d %H:%M:%S.%L') : time.strftime('%Y-%m-%d %H:%M:%S') base + " " + (time.utc? ? 'UTC' : time.strftime('%Z')) when /^\d{1,2}:\d{2}(?::\d{2})/ time.strftime('%H:%M:%S') + " " + (time.utc? ? 'UTC' : time.strftime('%Z')) when /^\d{1,2}:\d{2}/ time.strftime('%H:%M') + " " + (time.utc? ? 'UTC' : time.strftime('%Z')) else time.strftime('%Y-%m-%d %H:%M:%S') + " " + (time.utc? ? 'UTC' : time.strftime('%Z')) end end |
.has_timezone?(str) ⇒ Boolean
127 128 129 |
# File 'lib/tztr.rb', line 127 def has_timezone?(str) str.match?(/Z$|[+-]\d{2}:?\d{2}$| ?(?:UTC|GMT|[A-Z]{2,4}|[+-]\d{4})$/) end |
.parse(str, from: nil, to: 'UTC') ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/tztr.rb', line 113 def parse(str, from: nil, to: 'UTC') if has_timezone?(str) Time.parse(str) elsif from ENV['TZ'] = from t = Time.parse(str).utc ENV['TZ'] = to t.localtime else ENV['TZ'] = to Time.parse(str) end end |
.resolve_tz(input) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/tztr.rb', line 75 def resolve_tz(input) return input if input.nil? # Numeric offset: -7 -> Etc/GMT+7 (POSIX sign is inverted) if input.match?(/\A[+-]?\d{1,2}\z/) n = input.to_i return 'UTC' if n == 0 return "Etc/GMT#{n > 0 ? '-' : '+'}#{n.abs}" end TIMEZONE_ALIASES[input.downcase.tr(' ', '_')] || input end |
.translate(line, to: 'UTC', from: nil, format: nil) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/tztr.rb', line 89 def translate(line, to: 'UTC', from: nil, format: nil) to = resolve_tz(to) from = resolve_tz(from) ENV['TZ'] = to result = line.dup PATTERNS.each do |pattern| next unless result.match?(pattern) result.gsub!(pattern) do |match| begin time = parse(match, from:, to:) format_time(time.localtime, format, match) rescue ArgumentError match end end break result end result end |