Esempio n. 1
0
    def test_nice_date(self):
        for lang in self.test_config:
            i = 1
            while (self.test_config[lang].get('test_nice_date') and
                   self.test_config[lang]['test_nice_date'].get(str(i))):
                p = self.test_config[lang]['test_nice_date'][str(i)]
                dp = ast.literal_eval(p['datetime_param'])
                np = ast.literal_eval(p['now'])
                dt = datetime.datetime(
                    dp[0], dp[1], dp[2], dp[3], dp[4], dp[5])
                now = None if not np else datetime.datetime(
                    np[0], np[1], np[2], np[3], np[4], np[5])
                print('Testing for ' + lang + ' that ' + str(dt) +
                      ' is date ' + p['assertEqual'])
                self.assertEqual(p['assertEqual'],
                                 nice_date(dt, lang=lang, now=now))
                i = i + 1

        # test fall back to english
        dt = datetime.datetime(2018, 2, 4, 0, 2, 3)
        self.assertEqual(nice_date(
            dt, lang='invalid', now=datetime.datetime(2018, 2, 4, 0, 2, 3)),
            'today')

        # test all days in a year for all languages,
        # that some output is produced
        for lang in self.test_config:
            for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3) +
                       datetime.timedelta(n) for n in range(368)):
                self.assertTrue(len(nice_date(dt, lang=lang)) > 0)
Esempio n. 2
0
    def handle_get_next_appointment(self, message):
        """
        Generates the response for the intent asking for the next appointment
        in the connected Nextcloud calendar.
        :param message: The speech input message. Unused in this method.
        """
        del message  # unused by handler
        next_event = self.caldav_interface.get_next_event()
        output_data = {}
        dialog_filename = "next.appointment"

        if next_event is not None:
            title = next_event["title"]
            startdate_time = next_event["starttime"]
            enddate_time = next_event["endtime"]
            output_data["startdate"] = nice_date(startdate_time)
            if is_multiple_fulldays_event(startdate_time, enddate_time):
                output_data["enddate"] = nice_date(enddate_time)
            else:
                if not is_fullday_event(startdate_time, enddate_time):
                    output_data["time"] = nice_time(startdate_time)

            if title is not None:
                output_data["title"] = title

        # because we are using Python v3.7.x
        # the order of the keys of the dictionary is the the same as inserted,
        # so we can iterate over the keys to generate the correct dialog filenames
        for key in output_data:
            dialog_filename += "." + key
        self.speak_dialog(dialog_filename, output_data)
Esempio n. 3
0
    def test_nice_date(self):
        for lang in self.test_config:
            i = 1
            while (self.test_config[lang].get('test_nice_date') and
                   self.test_config[lang]['test_nice_date'].get(str(i))):
                p = self.test_config[lang]['test_nice_date'][str(i)]
                dp = ast.literal_eval(p['datetime_param'])
                np = ast.literal_eval(p['now'])
                dt = datetime.datetime(
                    dp[0], dp[1], dp[2], dp[3], dp[4], dp[5])
                now = None if not np else datetime.datetime(
                    np[0], np[1], np[2], np[3], np[4], np[5])
                print('Testing for ' + lang + ' that ' + str(dt) +
                      ' is date ' + p['assertEqual'])
                self.assertEqual(p['assertEqual'],
                                 nice_date(dt, lang=lang, now=now))
                i = i + 1

        # test fall back to english
        dt = datetime.datetime(2018, 2, 4, 0, 2, 3)
        self.assertEqual(nice_date(
            dt, lang='invalid', now=datetime.datetime(2018, 2, 4, 0, 2, 3)),
            'today')

        # test all days in a year for all languages,
        # that some output is produced
        for lang in self.test_config:
            for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3) +
                       datetime.timedelta(n) for n in range(368)):
                self.assertTrue(len(nice_date(dt, lang=lang)) > 0)
Esempio n. 4
0
    def dump_alarms(self, tag=""):
        # Useful when debugging
        dump = "\n" + "="*30 + " ALARMS " + tag + " " + "="*30 + "\n"
        dump += "raw = " + str(self.settings["alarm"]) + "\n\n"

        now_ts = to_utc(now_utc()).timestamp()
        dt = datetime.fromtimestamp(now_ts)
        dump += "now = {} ({})\n".format(
            nice_time(self.get_alarm_local(timestamp=now_ts),
                      speech=False, use_ampm=not self.use_24hour, use_24hour = self.use_24hour),
            now_ts)
        dump += "      U{} L{}\n".format(to_utc(dt), to_local(dt))
        dump += "\n\n"

        idx = 0
        for alarm in self.settings["alarm"]:
            dt = self.get_alarm_local(alarm)
            dump += "alarm[{}] - {} \n".format(idx, alarm)
            dump += "           Next: {} {}\n".format(
                nice_time(dt, speech=False, use_ampm= not self.use_24hour, use_24hour = self.use_24hour),
                nice_date(dt, now=now_local()))
            dump += "                 U{} L{}\n".format(dt, to_local(dt))
            if 'snooze' in alarm:
                dtOrig = self.get_alarm_local(timestamp=alarm['snooze'])
                dump += "           Orig: {} {}\n".format(
                    nice_time(dtOrig, speech=False, use_ampm= not self.use_24hour, use_24hour = self.use_24hour),
                    nice_date(dtOrig, now=now_local()))
            idx += 1

        dump += "="*75

        self.log.info(dump)
Esempio n. 5
0
    def handle_read_tasks_intent(self, message):
        if self._check_for_credentials(): return

        time = extract_datetime(message.data.get("utterance", ""))[0]
        project = self._extract_project(message.data.get("utterance", ""))

        tasks = self.todoist.get_tasks(time=time, project_name=project)

        if len(tasks) > 0:
            if not self.todoist.project_exists(project):
                project = ""
            self.speak_dialog('TasksOnTodo',
                              data={
                                  'project':
                                  project,
                                  'datetime':
                                  nice_date(time, now=datetime.datetime.now())
                              })
            for task in tasks:
                self.speak(task)
        else:
            self.speak_dialog('NoTasks',
                              data={
                                  'project':
                                  project or "",
                                  'datetime':
                                  nice_date(time, now=datetime.datetime.now())
                              })
Esempio n. 6
0
    def handle_get_appointment_date(self, message):
        """
        Handles the intent asking for events on a specific date.
        Checks the calendar on the specified date first,
        then responses with the number of planned events.
        If it's not 0, the user is asked if the events
        should be listed. If the user responds with 'yes'
        all events are listed with title, start and end time.
        :param message: The speech input message. Used to extract the specified date
        """
        self.log.info(f"Intent message: {message.data['utterance']}")
        extracted_date = extract_datetime(message.data['utterance'],
                                          datetime.now(self.timezone))[0]
        self.log.debug(f"Extracted date(s): {extracted_date}")
        events = self.caldav_interface.get_events_for_date(extracted_date)
        self.log.debug(f"Events on {extracted_date}: {events}")

        if len(events) == 0:
            self.speak_dialog("no.events.on.date", {
                "date":
                nice_date(extracted_date, now=datetime.now(self.timezone))
            })
        else:
            self.speak_dialog(
                "number.events.on.date", {
                    "date":
                    nice_date(extracted_date, now=datetime.now(self.timezone)),
                    "number_of_appointments":
                    len(events),
                    "plural":
                    "s" if len(events) > 1 else ""
                })
            list_events = self.ask_yesno("list.events.of.date", {
                "date":
                nice_date(extracted_date, now=datetime.now(self.timezone))
            })
            if list_events == "yes":
                self.speak_dialog(
                    "events.on.date", {
                        "date":
                        nice_date(extracted_date,
                                  now=datetime.now(self.timezone))
                    })
                for event in events:
                    title = event["title"]
                    startdate_time = event["starttime"]
                    enddate_time = event["endtime"]

                    self.speak_dialog(
                        "event.details", {
                            "title": title,
                            "starttime": nice_time(startdate_time,
                                                   use_ampm=True),
                            "endtime": nice_time(enddate_time, use_ampm=True)
                        })
Esempio n. 7
0
 def handle_date_last_weekend(self, message):
     # Strip year off nice_date as request is inherently close
     # Don't pass `now` to `nice_date` as a
     # request on Monday will return "yesterday"
     saturday_date = ', '.join(nice_date(extract_datetime(
                     self.texts.get('previous saturday'))[0]).split(', ')[:2])
     sunday_date = ', '.join(nice_date(extract_datetime(
                   self.texts.get('previous sunday'))[0]).split(', ')[:2])
     self.speak_dialog('date.last.weekend', {
         'direction': self.texts.get('last'),
         'saturday_date': saturday_date,
         'sunday_date': sunday_date
     })
Esempio n. 8
0
 def handle_date_future_weekend(self, message):
     # Strip year off nice_date as request is inherently close
     # Don't pass `now` to `nice_date` as a
     # request on Friday will return "tomorrow"
     saturday_date = ', '.join(nice_date(extract_datetime(
                     self.texts.get('this saturday'))[0]).split(', ')[:2])
     sunday_date = ', '.join(nice_date(extract_datetime(
                   self.texts.get('this sunday'))[0]).split(', ')[:2])
     self.speak_dialog('date.future.weekend', {
         'direction': self.texts.get('next'),
         'saturday_date': saturday_date,
         'sunday_date': sunday_date
     })
Esempio n. 9
0
 def select_event_date_not_none(self, title, date):
     """
     If the date of an event that should be deleted is given this
     method is used to handle the selection of the correct event if there are
     multiple events for that date. When the event is
     found the user is asked for confirmation and the event is deleted.
     :param date: datetime of the event that should be deleted
     :return: None
     """
     events_on_date = self.caldav_interface.get_events_for_date(date)
     if title is not None:
         event = next(
             (event for event in events_on_date if event["title"] == title),
             None)
         if event is not None:
             return event
     if len(events_on_date) == 0:
         self.speak_dialog("no.events.events.on.date",
                           {"date": nice_date(date)})
     if len(events_on_date) == 1:
         return events_on_date[0]
     if len(events_on_date) > 1:
         title_of_events = [
             event["title"] for event in events_on_date
             if event["title"] is not None
         ]
         self.speak_dialog("multiple.matching.events", {"detail": "date"})
         title = self.ask_selection(title_of_events,
                                    "event.selection.delete", None, 0.7)
         event = next(
             (event for event in events_on_date if event["title"] == title),
             None)
         return event
     return None
Esempio n. 10
0
 def date_str(self, d):
     if is_today(d):
         return 'today'
     elif is_tomorrow(d):
         return 'tomorrow'
     else:
         return nice_date(d.date())
Esempio n. 11
0
 def date_str(self, d):
     if is_today(d):
         return self.texts.get('today')
     elif is_tomorrow(d):
         return self.texts.get('tomorrow')
     else:
         return nice_date(d.date(), lang=self.lang)
Esempio n. 12
0
 def handle_num_appoint(self, message):
     if self.update_credentials() is False:  # No credentials
         return
     # clean/get date in utter
     utter = message.data["utterance"]
     when = extract_datetime(utter, datetime.datetime.now(), self.lang)[0]
     if when is None:
         when = extract_datetime("today", datetime.datetime.now(),
                                 self.lang)
     self.log.info(str(when))
     # get events
     events = self.get_events(when)
     nice_when = nice_date(when, now=now_local(), lang=self.lang)
     if events:
         num_events = len(events)
         if num_events == 1:
             self.speak_dialog("num.event", data={"when": nice_when})
         else:
             self.speak_dialog("num.events",
                               data={
                                   "num_events": num_events,
                                   "when": nice_when
                               })
     elif events is None or events == []:
         self.speak_dialog("no.events", data={"when": nice_when})
Esempio n. 13
0
    def handle_meetings_at_day(self, message):
        """Method is called when user speaks an intent in ``meetings.at.day.intent``.

        Calls the methods login_to_nextcloud() and get_appointment_info() to get
        the info of the users next appointment and gives the answer, for a specific day.

        speak() is a build-in MycroftSkill method, to let mycroft speak to the user.
        """
        self.login_to_nextcloud()
        try:
            start = get_date(message.data)
            list_of_events = self.get_appointment_info(from_start=start,
                                                       days=1,
                                                       get_next=False)
            if len(list_of_events) > 0:
                self.log.info(list_of_events)
                events_string = ' and '.join(event[1]\
                    for event in list_of_events)
                self.speak('On '+nice_date(start)+\
                    ' you have the following appointments: '+\
                        events_string)
            else:
                self.speak('You Don\'t have any appointments planned')
        except TypeError:
            self.speak('Sorry, I need you to tell me a month and day')
Esempio n. 14
0
def get_nice_event(event, is_on_date=False):
    """Transforms Events nicely spoken for Mycroft.

    nice_date() and nice_time() are functions from Mycroft.util.format that
    uses Lingua Franca to transform numbers and dates etc. to words.
    see mycroft.ai documentation at:
    https://mycroft-ai.gitbook.io/docs/mycroft-technologies/lingua-franca

    Args:
        event: Event extracted from Nextcloud.

    Returns:
        apmnt_date_time (str): The Date and Time of the next appointment  nicely spoken String.
        apmnt_title (str): The Title of the Appointment.
    """
    if type(event[0]) is date:
        apmnt_date_time = nice_date(event[0]) + ", all day "
        if is_on_date:
            apmnt_date_time = ", all day"
    else:
        apmnt_date_time = nice_date_time(event[0])
        if is_on_date:
            apmnt_date_time = ", at " + apmnt_date_time
    apmnt_title = str(event[1])
    return apmnt_date_time, apmnt_title
Esempio n. 15
0
    def handle_create_event(self, message):
        """
        Handler to create a new event in the calendar. It checked first
        if a title or date is given in the intent message. Then the user is
        asked for missing information as start time, duration or full-day event.
        If all information are present the event is created using the CalDav interface.
        :param message: the intent message
        :return: None
        """
        title, date = get_title_date_from_message(message)
        fullday = False

        while title is None:
            title = self.get_response("ask.for.title", {"action": "create"})
        self.log.info(f"set title of new event to: {title}")

        if date is None:
            date_response = self.get_response("ask.for.date")
            date, rest = extract_datetime(date_response)
        self.log.info(f"set date of new event to: {date}")

        title = self.remove_time_from_title(title)

        if date.time() == dt.time(0):
            time, rest = None, None
            pattern = re.compile(r"full\s*day")
            while time is None or time.time() == dt.time(0):
                rest = self.get_response("new.event.starttime",
                                         {"event": title})
                if rest is not None:
                    extracted = extract_datetime(rest)
                    if extracted is not None:
                        time, rest = extracted
                    if re.search(pattern, rest):
                        fullday = True
                        break

            if not fullday:
                date = datetime.combine(date.date(), time.time())

        duration = None
        while duration is None:
            if not fullday:
                duration_utterance = self.get_response(
                    "ask.duration.new.event")
                duration, rest = extract_duration(duration_utterance)
            else:
                duration_utterance = self.get_response("ask.fullday.duration")
                duration = extract_number(duration_utterance)

        self.log.info(
            f"New calendar event will be created. Title: {title}, Date: {str(date)}"
        )

        self.caldav_interface.create_new_event(title, date, duration, fullday)

        self.speak_dialog("successful.create.event", {
            "event": title,
            "date": nice_date(date)
        })
Esempio n. 16
0
 def delete_event_on_confirmation(self, event):
     """
     Asks the user for confirmation before a event is deleted. If user confirms the
     event is deleted from the Nextcloud calendar.
     :param event: dictionary with the details of the event
     """
     if event is not None:
         confirm = self.ask_yesno('confirm.delete.event', {
             "title": event["title"],
             "date": nice_date(event["starttime"])
         })
         if confirm == "yes":
             self.caldav_interface.delete_event(event)
             self.speak_dialog("successful.delete.event", {
                 "title": event["title"],
                 "date": nice_date(event["starttime"])
             })
             return
     self.speak_dialog("no.event.changed", {"action": "deleted"})
Esempio n. 17
0
	def handle_movie_year(self, message):
		""" Gets the year the movie was released.
		"""
		movie = message.data.get("movie")
		try:
			movieDetails = MOVIE.details(MOVIE.search(movie)[:1][0].id)
			self.speak_dialog("movie.year", {"movie": movieDetails.title, "year": nice_date(datetime.strptime(movieDetails.release_date.replace("-", " "), "%Y %m %d"))})
				
		## If the title can not be found, it creates an IndexError
		except IndexError:
			self.speak_dialog("no.info", {"movie": movie})
Esempio n. 18
0
	def handle_movie_information(self, message):
		""" Gets the short version and adds the TagLine for good measure.
		"""
		movie = message.data.get("movie")
		try:
			movieDetails = MOVIE.details(MOVIE.search(movie)[:1][0].id)
			self.speak_dialog("movie.info.response", {"movie": movieDetails.title, "year": nice_date(datetime.strptime(movieDetails.release_date.replace("-", " "), "%Y %m %d")), "budget": nice_number(movieDetails.budget)})
			self.speak(movieDetails.tagline)
				
		# If the title can not be found, it creates an IndexError
		except IndexError:
			self.speak_dialog("no.info", {"movie": movie})
Esempio n. 19
0
 def _read_unread_channel(self, chan):
     if self.state == "stopped":
         return
     msg_count = chan['msg_count']
     if msg_count:
         channel_message = self.dialog_renderer.render(
             "messages.for.channel", {'display_name': chan['display_name']})
         LOG.debug(channel_message)
         self.speak(channel_message)
         pfc = self.mm.posts.get_posts_for_channel(chan['channel_id'])
         order = pfc['order']
         # in case returned posts are less than number of unread
         # avoid 'index out of bounds'
         msg_count = msg_count if msg_count < len(order) else len(order)
         prev_date = ""
         for i in range(0, msg_count):
             if self.state == "stopped":
                 break
             # order starts with newest to oldest,
             # start to read the oldest of the unread
             post = pfc['posts'][order[msg_count - i - 1]]
             create_at = ""
             # nice_date does only support en-us yet - bummer!
             # MM timestamps are in millisecs, python in secs
             msg_date = nice_date(datetime.fromtimestamp(post['create_at'] /
                                                         1000),
                                  self.lang,
                                  now=datetime.now())
             if prev_date != msg_date:
                 create_at = msg_date + " "
                 prev_date = msg_date
             msg_time = nice_time(
                 datetime.fromtimestamp(post['create_at'] / 1000),
                 self.lang)
             create_at += msg_time
             msg = self.dialog_renderer.render(
                 "message", {
                     'user_name': self._get_user_name(post['user_id']),
                     'create_at': create_at,
                     'message': post['message']
                 })
             LOG.debug(msg)
             self.speak(msg, wait=True)
             time.sleep(.3)
         # mark channel as read
         self.mm.channels.view_channel(self.userid,
                                       {'channel_id': chan['channel_id']})
         # TODO clarify when to reset prev_unread/prev_mentions
         self.prev_unread = 0
         self.prev_mentions = 0
Esempio n. 20
0
    def __save_reminder_local(self, reminder, reminder_time):
        """ Speak verification and store the reminder. """
        # Choose dialog depending on the date
        if is_today(reminder_time):
            self.speak_dialog('SavingReminder',
                              {'timedate': nice_time(reminder_time, lang=self.lang)})
        elif is_tomorrow(reminder_time):
            self.speak_dialog('SavingReminderTomorrow',
                              {'timedate': nice_time(reminder_time, lang=self.lang)})
        else:
            self.speak_dialog('SavingReminderDate',
                              {'time': nice_time(reminder_time, lang=self.lang),
                               'date': nice_date(reminder_time, lang=self.lang)})

        # Store reminder
        serialized = serialize(reminder_time)
        if 'reminders' in self.settings:
            self.settings['reminders'].append((reminder, serialized))
        else:
            self.settings['reminders'] = [(reminder, serialized)]
Esempio n. 21
0
    def get_next_reminder(self, msg=None):
        """ Get the first upcoming reminder. """
        if len(self.settings.get('reminders', [])) > 0:
            reminders = [(r[0], deserialize(r[1]))
                         for r in self.settings['reminders']]
            next_reminder = sorted(reminders, key=lambda tup: tup[1])[0]

            if is_today(next_reminder[1]):
                self.speak_dialog('NextToday',
                                  data={'time': nice_time(next_reminder[1], lang=self.lang),
                                        'reminder': next_reminder[0]})
            elif is_tomorrow(next_reminder[1]):
                self.speak_dialog('NextTomorrow',
                                  data={'time': nice_time(next_reminder[1], lang=self.lang),
                                        'reminder': next_reminder[0]})
            else:
                self.speak_dialog('NextOtherDate',
                                  data={'time': nice_time(next_reminder[1], lang=self.lang),
                                        'date': nice_date(next_reminder[1], lang=self.lang),
                                        'reminder': next_reminder[0]})
        else:
            self.speak_dialog('NoUpcoming')
Esempio n. 22
0
 def handle_day_appoint(self, message):
     # clean/get date in utter
     if self.update_credentials() is False:  # No credentials
         return
     utter = message.data["utterance"]
     when = extract_datetime(utter, datetime.datetime.now(), self.lang)[0]
     if when is None:
         when = extract_datetime("today", datetime.datetime.now(),
                                 self.lang)
     self.log.info(str(when))
     # get events
     events = self.get_events(when)
     nice_when = nice_date(when, now=now_local(), lang=self.lang)
     if events:
         # say first
         self.speak_dialog("day",
                           data={
                               "num_events":
                               len(events),
                               "event":
                               events[0].get("event"),
                               "when":
                               nice_when,
                               "time":
                               nice_time(events[0].get("datetime"),
                                         use_ampm=True)
                           })
         # Say follow up
         for x in range(1, len(events)):
             self.speak_dialog("day.followed",
                               data={
                                   "event":
                                   events[x].get("event"),
                                   "time":
                                   nice_time(events[x].get("datetime"),
                                             use_ampm=True)
                               })
     elif events is None or events == []:
         self.speak_dialog("no.events", data={"when": nice_when})
    def handle_cinema_deckchair(self, message):
        try:
            now_date = datetime.now()
            # 1. Scrape website for movie on this date
            try:
                program_tr_list = self.cinema_program.fetch(
                    cache=[join(self.file_system.path), now_date])
            except (exceptions.ConnectionError or exceptions.HTTPError
                    or exceptions.Timeout or exceptions.TooManyRedirects) as e:
                self.log.error('Error: {0}'.format(e))
                self.speak_dialog('error.http')
                return

            # 2. Extract date from utterance, or default to today
            when = extract_datetime(message.data.get('utterance'))[0]
            if self.testing_date is not None:
                when = self.testing_date

            # 3. Test if date is in deckchair program range
            first_date = self._get_date_from_list(program_tr_list, 'first')
            last_date = self._get_date_from_list(program_tr_list, 'last')
            if when < first_date or last_date < when:
                self.speak_dialog(
                    'error.datenotfound', {
                        'when': nice_date(when, now=now_date),
                        'first_date': nice_date(first_date, now=now_date),
                        'last_date': nice_date(last_date, now=now_date)
                    })
                return False

            # 4. Find movie on provided date
            try:
                date_row = next(
                    (x for x in program_tr_list
                     if x.getchildren()[0].text == when.strftime('%A %-d %B')))
            except StopIteration:
                self.log.info('Date note found: {}'.format(
                    when.strftime('%A %-d %B')))
                return self.speak_dialog(
                    'error.datenotfound', {
                        'when': nice_date(when, now=now_date),
                        'first_date': nice_date(first_date, now=now_date),
                        'last_date': nice_date(last_date, now=now_date)
                    })
            movies_on_date = self._add_movie_from_date(date_row,
                                                       movies_on_date=[])

            # 5. Construct message to return
            movie_details_dialog = []
            for movie in movies_on_date:
                if len(movie_details_dialog) > 0:
                    movie_details_dialog.append(self.translate('and'))
                movie_title = movie.getchildren()[0].getchildren()[0].text
                movie_time = nice_time(
                    when.replace(hour=int(movie.getchildren()[1].text[0:-5]),
                                 minute=int(
                                     movie.getchildren()[1].text[-4:-2])))
                movie_details_dialog.append(
                    self.translate('movie.at.time', {
                        'title': movie_title,
                        'time': movie_time
                    }))

            self.speak_dialog(
                'whats.on', {
                    'when': nice_date(when, now=datetime.now()),
                    'movie_details': ', '.join(movie_details_dialog)
                })

            # 6. Fetch data and set context for follow up questions
            # Reset data from previous requests.
            self._movies_on_requested_date = []
            self._current_movie_context = ''
            for movie in movies_on_date:
                movie_details = self._fetch_movie_details(movie)
                self._movie_dict[movie_details['title']] = movie_details
                self._movies_on_requested_date.append(
                    movie.getchildren()[0].getchildren()[0].text)
            self.set_context('DeckchairContext', 'True')

        except Exception as e:
            self.log.exception(format(e))
            self.speak_dialog('error')
Esempio n. 24
0
def _future_time_delta_en(future_date, anchor=None):
    """
        Return a nice string representing a future datetime in english.
        If you need to explicitly set the reference that the future is relative
        to, just pass it in as a second datetime object.
        """

    if not anchor:
        anchor = now_local()

    delta = future_date - anchor
    seconds = delta.seconds
    days = delta.days
    global_seconds = days * 24 * 60 * 60 + seconds
    minutes = int(round(seconds / 60.) % 60)
    day_changes = (to_local(future_date) - to_local(datetime(*anchor.timetuple()[:3]))).days

    if days < 0:
        raise AttributeError("Negative timedelta. I can only do futures!")

    if global_seconds <= 45:
        if seconds == 1:
            return "a second"
        if seconds <= 15:
            return 'a moment'
        else:

            return str(seconds) + " seconds"

    elif global_seconds < 60 * 59.5:
        if seconds <= 90:
            return 'about a minute'
        elif seconds <= 60 * 4.5:
            return str(minutes) + " minutes"

    elif anchor.day == future_date.day:
        h = seconds // 3600
        if h == 1:
            hour_string = "1 hour"
        else:
            hour_string = str(h) + " hours"
        if minutes > 4:
            hour_string += " and " + str(minutes) + " minutes"
        return hour_string

    elif global_seconds <= 60 * 60 * 24 * 2 and day_changes == 1:
        if future_date.hour == 0:
            if future_date.minute == 0:
                return 'midnight tonight'
        return 'tomorrow at %s' % nice_time_en(future_date)

    elif global_seconds <= 60 * 60 * 24 * 8 and day_changes <= 7:
        if day_changes <= 3 or (future_date.weekday() == 6 and anchor.weekday() != 6):
            return '%s at %s' % (future_date.strftime('%A'), nice_time_en(future_date))
        elif (future_date.weekday() > anchor.weekday() or anchor.weekday() == 6) and day_changes <= 6:
            return 'this %s at %s' % (future_date.strftime('%A'), nice_time_en(future_date))
        else:
            return 'next %s at %s' % (future_date.strftime('%A'), nice_time_en(future_date))

    else:
        # needs to be here
        from mycroft.util.format import nice_date
        return nice_date(future_date)
Esempio n. 25
0
 def test_invalid_lang_code(self):
     dt = datetime.datetime(2018, 2, 4, 0, 2, 3)
     with self.assertRaises(UnsupportedLanguageError):
         nice_date(dt, lang='invalid', now=dt)
Esempio n. 26
0
    def handle_query_date(self, message, response_type="simple"):
        utt = message.data.get('utterance', "").lower()
        try:
            extract = extract_datetime(utt)
        except Exception:
            self.speak_dialog('date.not.found')
            return
        day = extract[0] if extract else now_local()

        # check if a Holiday was requested, e.g. "What day is Christmas?"
        year = extract_number(utt)
        if not year or year < 1500 or year > 3000:  # filter out non-years
            year = day.year
        all_holidays = {}
        # TODO: How to pick a location for holidays?
        for st in holidays.US.STATES:
            holiday_dict = holidays.US(years=[year], state=st)
            for d, name in holiday_dict.items():
                if name not in all_holidays:
                    all_holidays[name] = d
        for name in all_holidays:
            d = all_holidays[name]
            # Uncomment to display all holidays in the database
            # self.log.info("Day, name: " +str(d) + " " + str(name))
            if name.replace(" Day", "").lower() in utt:
                day = d
                break

        location = self._extract_location(utt)
        today = to_local(now_utc())
        if location:
            # TODO: Timezone math!
            if (day.year == today.year and day.month == today.month
                    and day.day == today.day):
                day = now_utc()  # for questions ~ "what is the day in sydney"
            day = self.get_local_datetime(location, dtUTC=day)
        if not day:
            return  # failed in timezone lookup

        speak_date = nice_date(day, lang=self.lang)
        # speak it
        if response_type == "simple":
            self.speak_dialog("date", {"date": speak_date})
        elif response_type == "relative":
            # remove time data to get clean dates
            day_date = day.replace(hour=0, minute=0, second=0, microsecond=0)
            today_date = today.replace(hour=0,
                                       minute=0,
                                       second=0,
                                       microsecond=0)
            num_days = (day_date - today_date).days
            if num_days >= 0:
                speak_num_days = nice_duration(num_days * 86400)
                self.speak_dialog("date.relative.future", {
                    "date": speak_date,
                    "num_days": speak_num_days
                })
            else:
                # if in the past, make positive before getting duration
                speak_num_days = nice_duration(num_days * -86400)
                self.speak_dialog("date.relative.past", {
                    "date": speak_date,
                    "num_days": speak_num_days
                })

        # and briefly show the date
        self.answering_query = True
        self.show_date(location, day=day)
        time.sleep(10)
        mycroft.audio.wait_while_speaking()
        if self.platform == "mycroft_mark_1":
            self.enclosure.mouth_reset()
            self.enclosure.activate_mouth_events()
        self.answering_query = False
        self.displayed_time = None
Esempio n. 27
0
 def format_date(self, date: datetime.date):
     return nice_date(datetime.datetime(date.year, date.month, date.day),
                      now=datetime.datetime.now(tz=self.timezone))
Esempio n. 28
0
 def getMovieDate(self):
     return nice_date(
         datetime.strptime(self.movieDetails.release_date.replace("-", " "),
                           "%Y %m %d"))