#!/usr/bin/env python

# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import datetime
import math
import re


class TimezoneInfo(datetime.tzinfo):

  def __init__(self, h, m):
    self._name = "UTC"
    if h != 0 and m != 0:
      self._name += "%+03d:%2d" % (h, m)
    self._delta = datetime.timedelta(hours=h, minutes=math.copysign(m, h))

  def utcoffset(self, dt):
    return self._delta

  def tzname(self, dt):
    return self._name

  def dst(self, dt):
    return datetime.timedelta(0)


UTC = TimezoneInfo(0, 0)

# ref https://www.ietf.org/rfc/rfc3339.txt
_re_rfc3339 = re.compile(
    r"(\d\d\d\d)-(\d\d)-(\d\d)"  # full-date
    r"[ Tt]"  # Separator
    r"(\d\d):(\d\d):(\d\d)([.,]\d+)?"  # partial-time
    r"([zZ ]|[-+]\d\d?:\d\d)?",  # time-offset
    re.VERBOSE + re.IGNORECASE)
_re_timezone = re.compile(r"([-+])(\d\d?):?(\d\d)?")


def parse_rfc3339(s):
  if isinstance(s, datetime.datetime):
    # no need to parse it, just make sure it has a timezone.
    if not s.tzinfo:
      return s.replace(tzinfo=UTC)
    return s
  groups = _re_rfc3339.search(s).groups()
  dt = [0] * 7
  for x in range(6):
    dt[x] = int(groups[x])
  if groups[6] is not None:
    dt[6] = int(groups[6])
  tz = UTC
  if groups[7] is not None and groups[7] != "Z" and groups[7] != "z":
    tz_groups = _re_timezone.search(groups[7]).groups()
    hour = int(tz_groups[1])
    minute = 0
    if tz_groups[0] == "-":
      hour *= -1
    if tz_groups[2]:
      minute = int(tz_groups[2])
    tz = TimezoneInfo(hour, minute)
  return datetime.datetime(
      year=dt[0],
      month=dt[1],
      day=dt[2],
      hour=dt[3],
      minute=dt[4],
      second=dt[5],
      microsecond=dt[6],
      tzinfo=tz)


def format_rfc3339(date_time):
  if date_time.tzinfo is None:
    date_time = date_time.replace(tzinfo=UTC)
  date_time = date_time.astimezone(UTC)
  return date_time.strftime("%Y-%m-%dT%H:%M:%SZ")
