{"record":{"id":"83c000625bba4e81","repo":"puppetlabs/puppet","slug":"using-a-timezone-designator-in-format-specificatio","errorCode":null,"errorMessage":"Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument","messagePattern":"Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/time/timestamp.rb","lineNumber":98,"sourceCode":"        if parsed.include?(:leftover) || (has_timezone && parsed.include?(:zone))\n          parsed = nil\n          next\n        end\n        break\n      end\n      if parsed.nil?\n        raise ArgumentError, _(\n          \"Unable to parse '%{str}' using any of the formats %{formats}\"\n        ) % { str: str, formats: format.join(', ') }\n      end\n    else\n      parsed = DateTime._strptime(str, format)\n      if parsed.nil? || parsed.include?(:leftover)\n        raise ArgumentError, _(\"Unable to parse '%{str}' using format '%{format}'\") % { str: str, format: format }\n      end\n\n      if has_timezone && parsed.include?(:zone)\n        raise ArgumentError, _(\n          'Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument'\n        )\n      end\n    end\n    unless has_timezone\n      timezone = parsed[:zone]\n      has_timezone = !timezone.nil?\n    end\n    fraction = parsed[:sec_fraction]\n\n    # Convert msec rational found in _strptime hash to usec\n    fraction *= 1_000_000 unless fraction.nil?\n\n    # Create the Time instance and adjust for timezone\n    parsed_time = ::Time.utc(parsed[:year], parsed[:mon], parsed[:mday], parsed[:hour], parsed[:min], parsed[:sec], fraction)\n    parsed_time -= utc_offset(timezone) if has_timezone\n\n    # Convert to Timestamp","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/time/timestamp.rb#L80-L116","documentation":"After a successful parse, Timestamp.parse checks whether an explicit timezone argument was given AND the parsed result contains a :zone key (i.e. the format contained a timezone designator like %Z or %z and the string satisfied it). Because both would determine the zone, the combination is rejected with ArgumentError - the two are mutually exclusive by design.","triggerScenarios":"Timestamp.parse('2023-01-31 12:00:00 UTC', '%F %T %Z', '+00:00'), or Puppet DSL Timestamp('... %Z format...', timezone => '+02:00'). Also with the default format set: passing a timezone argument selects DEFAULT_FORMATS_WO_TZ precisely to avoid this, so it fires mainly with user-supplied formats.","commonSituations":"Layered defaults: a helper always passes a timezone argument while the caller's format string already encodes the zone; migrating configs that grew both mechanisms; ISO strings ending in 'Z' or '+02:00' paired with an explicit zone parameter.","solutions":["Pick one mechanism: either give the timezone argument and use zone-less formats ('%F %T'), or embed %Z/%z in the format and pass no timezone","Strip the zone from the string when a timezone argument must win: raw.sub(/\\s*(UTC|[+-]\\d{2}:?\\d{2}|Z)\\z/, '')","When the string's own zone is authoritative, drop the timezone argument entirely","Audit helper functions that inject a default timezone arg on every call"],"exampleFix":"// before\nts = Timestamp.parse('2023-01-31 12:00:00 UTC', '%F %T %Z', '+01:00')   # raise\n\n// after (string zone wins)\nts = Timestamp.parse('2023-01-31 12:00:00 UTC', '%F %T %Z')\n// after (argument wins)\nts = Timestamp.parse('2023-01-31 12:00:00', '%F %T', '+01:00')","handlingStrategy":"validation","validationCode":"has_zone_directive = fmt.match?(/%[-_0-9^#]*[zZ]/)\nraise ConfigError, 'format already encodes a zone - drop the timezone argument' if has_zone_directive && timezone\nts = Timestamp.parse(str, fmt)","typeGuard":null,"tryCatchPattern":"begin\n  ts = Timestamp.parse(str, fmt, timezone)\nrescue ArgumentError => e\n  timezone = nil   # let the embedded %Z/%z win and retry once\n  retry if e.message.include?('mutually exclusive')\n  raise\nend","preventionTips":["Choose one zone mechanism per call: format designator OR explicit argument, never both","Note :default auto-selects zone-less formats when a timezone argument is present - rely on that","Strip trailing zone tokens from strings when a timezone argument must be authoritative"],"tags":["puppet","timestamp","timezone","conflicting-arguments","argument-error"],"backgroundTag":"conflicting-timezone-arguments","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}