def test_init_is_today(init_args): """If passed an object without a timetuple method, use today.""" today = datetime.date.today().timetuple() if init_args is not None: ddate_obj = DDate(init_args).date.timetuple() else: ddate_obj = DDate().date.timetuple() assert today.tm_yday == ddate_obj.tm_yday assert today.tm_mon == ddate_obj.tm_mon
def test_discordian_holiday(dateobj, holidayexp, strexp): """Ensure the holidays are correctly accounted for.""" hday = DDate(dateobj) assert hday.holiday == holidayexp # have to use endswith just in case today is the test day assert str(hday).endswith("{0} Celebrate {1}!".format(strexp, holidayexp))
def when(inp, say=None): #"Shows the countdown to the new episode of My Little Pony: Friendship is Magic!" try: ep = ponyapi.newest() now, then, td = get_time(ep) seasonep = "" if inp == "discord": return "%s will air on %s" % (ep[u"name"], DDate(then)) if ep[u"is_movie"]: seasonep = "(a movie)" else: seasonep = "(season %d episode %d)" % (ep[u"season"], ep[u"episode"]) reply = "%s %s will air on %s in %d days!" % ( ep[u"name"], seasonep, then.strftime("%a, %d %b %Y %H:%M:%S"), td.days) return reply except: return "404! We're on hiatus!"
def __init__(self, discordian=False, eve_real=False, eve_game=False, date=None): self.discordian = discordian self.eve_real = eve_real self.eve_game = eve_game if self.discordian: self.max_width = 14 self.date = date or DDate() now = DDate() self.context = cmp( int("{0}{1}".format(self.date.year, self.date.season)), int("{0}{1}".format(now.year, now.season))) self.calendar = discordian_calendar(self.date) self.month = self.date.SEASONS[self.date.season] self.ending_days = ["70", "71", "72", "73"] self.day_of_month = self.date.day_of_season self.weekday_abbrs = [d[:2].title() for d in self.date.WEEKDAYS] else: self.max_width = 20 now = datetime.datetime.now() self.date = date or now self.context = cmp( int("{0}{1}".format(self.date.year, str(self.date.month).rjust(2, "0"))), int("{0}{1}".format(now.year, str(now.month).rjust(2, "0"))), ) self.month = self.date.strftime("%B") # start the week on Sunday self.calendar = calendar.TextCalendar(6).formatmonth( self.date.year, self.date.month, ).splitlines()[2:] self.ending_days = ["28", "29", "30", "31"] self.day_of_month = self.date.strftime("%d") self.weekday_abbrs = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] if self.eve_real: self.year = 23236 + (self.date.year - 1898) elif self.eve_game: self.year = "YC {0}".format(self.date.year - 1898) else: self.year = self.date.year
def test_data_in_repr(): """Ensure object data is in the repr.""" ddate_obj = DDate(datetime.date(year=2012, month=2, day=29)) assert str(hex(id(ddate_obj))) in repr(ddate_obj) for attr in dir(ddate_obj): if not attr.startswith("_") and attr.lower() == attr: assert str(getattr(ddate_obj, attr)) in repr(ddate_obj)
def discordianCalendar(day): discordianDay = DDate(day) dayInfo = {} dayInfo['DayName'] = DDate.WEEKDAYS[discordianDay.day_of_week] dayInfo['MonthName'] = DDate.SEASONS[discordianDay.season] dayInfo['DayNum'] = str(discordianDay.day_of_season) dayInfo['MonthNum'] = str(discordianDay.season) dayInfo['YearNum'] = 'YOLD ' + str(discordianDay.year) dayInfo['Format'] = 'Discordian' return dayInfo
def test_days_of_the_year(dateobj, weekday, season, dayofseason, year, strexp): """Test specific days of the year.""" ddate_obj = DDate(dateobj) if weekday is None: # checks for st tibs edge cases, avoids TypeError's on [None] assert ddate_obj.day_of_week == weekday assert ddate_obj.season == season else: assert ddate_obj.WEEKDAYS[ddate_obj.day_of_week] == weekday assert ddate_obj.SEASONS[ddate_obj.season] == season assert ddate_obj.day_of_season == dayofseason assert ddate_obj.year == year assert str(ddate_obj) == strexp
def discordian_calendar(date): """Simulate calendar.TextCalendar for discordian dates. Args: date: a DDate object Returns: list of strings to make a calendar month """ first_day_of_season = DDate( datetime.date( year=date.date.year, month=date.date.month, day=date.date.day, ) - datetime.timedelta(days=date.day_of_season - 1), ) weeks = [] first_week = True start_day = first_day_of_season.day_of_week for week in range(1, 77, 5): if first_week: weeks.append("{0}{1}".format( " " * start_day, " ".join( [str(x).rjust(2, " ") for x in range(1, 6 - start_day)]), )) first_week = False else: week_str = " ".join([ str(x) for x in range(week - start_day, min((week - start_day) + 5, 74)) ]) if week_str: weeks.append(week_str) return weeks
def discordian_date(self, tweet): # Expects single tweet (list) text = str("@" + tweet[0] + " " + str(DDate())) print(text) self.reply_semiman(text, tweet[2])
def ddate(inp): return str(DDate())
def nextshow(update: Update, context: CallbackContext) -> None: """Bot /next callback Posts the next scheduled show for a given slug/name and timezone""" # Message edit. if update.message is None: return args = update.message.text.split(" ") # Which show if len(args) < 2: slug = next_show_default elif args[1].lower() in domains: slug = args[1].lower() else: slug = next_show_default args.insert(1, "") # reverse shift to offer timezone domain = domains[slug.lower()] try: r = requests.get("https://{}/nextshow/".format(domain)) if r.status_code != 200: raise Exception("API returned " + str(r.status_code)) except Exception as e: update.message.reply_text(text="Error: " + str(e)) raise e showtime = datetime.utcfromtimestamp(int(r.text)) # Start update job if "pin" in args: user = update.effective_chat.get_member(update.effective_user.id) if not user.can_pin_messages and user.status != "creator": update.message.reply_text(text="You aren't allowed to do that") return ctx = { "chat": update.effective_chat, "message": None, "slug": slug, "showtime": showtime, } logging.info( "Scheduled next-pin job, %s (%s) for %s", update.effective_user.name, update.effective_user.id, update.effective_chat.title, ) updater.job_queue.run_repeating( next_pin_callback, 60, 0, context=ctx, name=f"next_pin_{update.effective_chat.id}", ) return # Timezones if len(args) < 3: # no TZ tzstr = "America/New_York" else: tzstr = args[2] if tzstr.lower() in ["ddate", "discordian"]: datestr = str(DDate(showtime)) if datestr.startswith("Today is "): datestr = datestr[9:] elif tzstr.lower() in ["beat", "swatch", "internet"]: datestr = beat(showtime) else: if tzstr.lower() in timezones: # custom map tzstr = timezones[args[2].lower()] elif len(tzstr) < 5: # probably "EDT" style tzstr = tzstr.upper() # Otherwise try verbatim tzobj = tz.gettz(tzstr) if tzobj is None: update.message.reply_text(text="Sorry, I don't understand") # TZ or show return datestr = ( showtime.astimezone(tzobj).strftime("%a %e %b, %H:%M %Z").replace(" ", " ") ) delta = showtime - datetime.utcnow() if delta.total_seconds() < 0: update.effective_chat.send_message("A show is currently live or just ended!") return deltastr = "{} days, {:02}:{:02}".format( delta.days, delta.seconds // (60 * 60), (delta.seconds // 60) % 60 ) update.effective_chat.send_message( text="The next {} is {}. That's {} from now.".format( show_names[domain], datestr, deltastr ) )
def handle_today(self, data, match): self.send(str(DDate()), data)
def handle_date(self, data, match): year = int(match.groupdict()['year']) month = int(match.groupdict()['month']) day = int(match.groupdict()['day']) self.send(str(DDate(datetime.date(year=year, month=month, day=day))), data)
def dd(bot, trigger): bot.say(str(DDate()))
def discordian_calendar(season=None, year=None, dtobj=None): """Prints a discordian calendar for a particular season and year. Args:: season: integer cardinal season from 1 to 5 year: integer discordian year from 1166 to MAXYEAR + 1166 dtobj: datetime object to instatiate the calendar from (Gregorian) """ now = DDate(dtobj) moved_year = None if season is None: season = now.season elif season.lower() == "next": season, moved_year = _season_overflow(now.season or 0 + 1, moved_year, now) else: # allow for +1, -2, for seasons... for symbol, oper in zip(("+", "-"), (operator.add, operator.sub)): if symbol in season: try: amount = int(season.strip(symbol)) except ValueError: raise ValueError("unknown season: {}".format(season)) else: season, moved_year = _season_overflow( oper(now.season or 0, amount), moved_year, now, ) break else: # allow to use the season name or some starting part of it input_name = season.lower() for season_name in now.SEASONS: _name = season_name.lower() if input_name == _name or any( [n.startswith(input_name) for n in _name.split(" ")]): season = now.SEASONS.index(season_name) break else: try: # last try with a literal int being passed in season = int(season) except ValueError: raise ValueError("unknown season: {}".format(season)) else: if not 1 <= season <= 5: raise ValueError("season must be in 1..5") season -= 1 # allowing cardinal numbers from the user if year is None: year = moved_year or now.year elif year.lower() == "next": year = (moved_year or now.year) + 1 else: for symbol, oper in zip(("+", "-"), (operator.add, operator.sub)): if symbol in year: year = oper(moved_year or now.year, int(year.strip(symbol))) break else: try: year = int(year) except ValueError: raise ValueError("invalid year: {}".format(year)) if not MINYEAR <= year <= MAXYEAR: # otherwise this error isn't that helpful raise ValueError("year must be in {}..{}".format(MINYEAR, MAXYEAR)) if now.day_of_season is None: if is_leap_year(year - 1166): day_of_season = None else: day_of_season = 59 season = season or 0 else: day_of_season = now.day_of_season if day_of_season: cal_date = DDate(year=year, season=season, day_of_season=day_of_season) cal = MultiCalendar(discordian=True, date=cal_date) cal.print_calendar() else: print("{} in YOLD {}".format(now.holiday, year))