def extract_datetime(text, anchorDate=None, lang="en-us", default_time=None): """ Extracts date and time information from a sentence. Parses many of the common ways that humans express dates and times, including relative dates like "5 days from today", "tomorrow', and "Tuesday". Vague terminology are given arbitrary values, like: - morning = 8 AM - afternoon = 3 PM - evening = 7 PM If a time isn't supplied or implied, the function defaults to 12 AM Args: text (str): the text to be interpreted anchorDate (:obj:`datetime`, optional): the date to be used for relative dating (for example, what does "tomorrow" mean?). Defaults to the current local date/time. lang (string): the BCP-47 code for the language to use default_time (datetime.time): time to use if none was found in the input string. Returns: [:obj:`datetime`, :obj:`str`]: 'datetime' is the extracted date as a datetime object in the user's local timezone. 'leftover_string' is the original phrase with all date and time related keywords stripped out. See examples for further clarification Returns 'None' if no date or time related text is found. Examples: >>> extract_datetime( ... "What is the weather like the day after tomorrow?", ... datetime(2017, 06, 30, 00, 00) ... ) [datetime.datetime(2017, 7, 2, 0, 0), 'what is weather like'] >>> extract_datetime( ... "Set up an appointment 2 weeks from Sunday at 5 pm", ... datetime(2016, 02, 19, 00, 00) ... ) [datetime.datetime(2016, 3, 6, 17, 0), 'set up appointment'] >>> extract_datetime( ... "Set up an appointment", ... datetime(2016, 02, 19, 00, 00) ... ) None """ lang_lower = str(lang).lower() if not anchorDate: anchorDate = now_local() if lang_lower.startswith("en"): return extract_datetime_en(text, anchorDate, default_time) elif lang_lower.startswith("es"): return extract_datetime_es(text, anchorDate, default_time) elif lang_lower.startswith("pt"): return extract_datetime_pt(text, anchorDate, default_time) elif lang_lower.startswith("it"): return extract_datetime_it(text, anchorDate, default_time) elif lang_lower.startswith("fr"): return extract_datetime_fr(text, anchorDate, default_time) elif lang_lower.startswith("sv"): return extract_datetime_sv(text, anchorDate, default_time) elif lang_lower.startswith("de"): return extract_datetime_de(text, anchorDate, default_time) # TODO: extract_datetime for other languages LOG.warning('Language "{}" not recognized! Please make sure your ' 'language is one of the following: ' 'en, es, pt, it, fr, sv, de.'.format(lang_lower)) return text
def extract_datetime(text, anchorDate=None, lang=None, default_time=None): """ Extracts date and time information from a sentence. Parses many of the common ways that humans express dates and times, including relative dates like "5 days from today", "tomorrow', and "Tuesday". Vague terminology are given arbitrary values, like: - morning = 8 AM - afternoon = 3 PM - evening = 7 PM If a time isn't supplied or implied, the function defaults to 12 AM Args: text (str): the text to be interpreted anchorDate (:obj:`datetime`, optional): the date to be used for relative dating (for example, what does "tomorrow" mean?). Defaults to the current local date/time. lang (str): the BCP-47 code for the language to use, None uses default default_time (datetime.time): time to use if none was found in the input string. Returns: [:obj:`datetime`, :obj:`str`]: 'datetime' is the extracted date as a datetime object in the user's local timezone. 'leftover_string' is the original phrase with all date and time related keywords stripped out. See examples for further clarification Returns 'None' if no date or time related text is found. Examples: >>> extract_datetime( ... "What is the weather like the day after tomorrow?", ... datetime(2017, 06, 30, 00, 00) ... ) [datetime.datetime(2017, 7, 2, 0, 0), 'what is weather like'] >>> extract_datetime( ... "Set up an appointment 2 weeks from Sunday at 5 pm", ... datetime(2016, 02, 19, 00, 00) ... ) [datetime.datetime(2016, 3, 6, 17, 0), 'set up appointment'] >>> extract_datetime( ... "Set up an appointment", ... datetime(2016, 02, 19, 00, 00) ... ) None """ lang_code = get_primary_lang_code(lang) if not anchorDate: anchorDate = now_local() if lang_code == "en": return extract_datetime_en(text, anchorDate, default_time) elif lang_code == "es": return extract_datetime_es(text, anchorDate, default_time) elif lang_code == "pt": return extract_datetime_pt(text, anchorDate, default_time) elif lang_code == "it": return extract_datetime_it(text, anchorDate, default_time) elif lang_code == "fr": return extract_datetime_fr(text, anchorDate, default_time) elif lang_code == "sv": return extract_datetime_sv(text, anchorDate, default_time) elif lang_code == "de": return extract_datetime_de(text, anchorDate, default_time) elif lang_code == "da": return extract_datetime_da(text, anchorDate, default_time) elif lang_code == "ar": return extract_datetime_ar(text, anchorDate, default_time) # TODO: extract_datetime for other languages _log_unsupported_language(lang_code, ['en', 'es', 'pt', 'it', 'fr', 'sv', 'de', 'da']) return text
def handle_generate_intent(self, message): # month = message.data.get("Month") # self.log.error(month) # For test. month = "this" if not month: self.speak_dialog("error.input.mh") return category = self.get_response("category.mh") if not category or category not in [ "pressure", "diabetes", "pain", "temperature", "heartbeat" ]: self.speak_dialog("error.input.mh") return person = self.get_response("person.mh") person = "" if not person else person current_datetime = now_local() # Multi languages support should be implemented here. if month == "this" or month == "current": to_datetime = current_datetime elif month == "last" or month == "previous": to_datetime = current_datetime.replace( day=1, hour=23, minute=59, second=59, microsecond=0) - timedelta(days=1) from_datetime = to_datetime.replace(day=1, hour=0, minute=0, second=0, microsecond=0) health_data_list = self.get_data(from_datetime, to_datetime, category, person) health_data = [] for data in health_data_list: health_data.append({ 'Datetime': data[0].strftime("%m/%d/%Y %H:%M:%S"), 'Category': data[1], 'Value': data[2], 'Parameter': data[3], 'Person': data[4] }) table = json2html.convert(json=health_data) content = """ <!DOCTYPE html><html><head><style>table{font-family:arial,sans-serif; border-collapse:collapse;width:100%;}td,th{border:1px solid #dddddd; text-align:left;padding:8px;}tr:nth-child(even) {background-color: #dddddd;}</style></head><body>""" content = """ {0}<h2>Health Data: {1} to {2}</h2> {3}</body></html>""".format( content, from_datetime.strftime("%m/%d/%Y %H:%M:%S"), to_datetime.strftime("%m/%d/%Y %H:%M:%S"), table) # self.send_email( # "Health Report - {0}".format(category.upper()), # content) # For test. message = Mail(from_email="Mycroft Health <*****@*****.**>", to_emails="*****@*****.**", subject="Mycroft Health Report - {0}".format( category.upper()), html_content=content) # Please provide your own Api key for testing as it's not wise to # expose Api key in public. api_key = "<your sendgrid API key>" try: sg = SendGridAPIClient(api_key) _ = sg.send(message) except Exception: pass
def handle_skill_study(self, message): # Give a welcome message to the user self.speak_dialog('skill.welcome') participantnumber = self.get_response('skill.participant.number') # Get the tasks the user wants to accomplish tasks = [] task1 = self.get_response('tasks.task1') self.speak_dialog('tasks.task1.confirmation', data={"task1": task1}) tasks.append(task1) another_task = self.ask_yesno('tasks.another.task') while another_task != 'yes' and another_task != 'no': self.speak_dialog('skill.task.could.not.understand') another_task = self.ask_yesno('tasks.another.task') if another_task == "yes": task2 = self.get_response('tasks.task2') tasks.append(task2) elif another_task == "no": self.speak_dialog('tasks.moveon') last_task = self.ask_yesno('tasks.last.task') while last_task != 'yes' and last_task != 'no': self.speak_dialog('skill.last.task.could.not.understand') last_task = self.ask_yesno('tasks.last.task') if last_task == "yes": task3 = self.get_response('tasks.task3') tasks.append(task3) elif last_task == "no": self.speak_dialog('tasks.moveon') if len(tasks) == 1: number_of_tasks = "1 task" if len(tasks) > 1: number_of_tasks = "{} tasks".format(len(tasks)) self.speak_dialog('tasks.confirmation', data={"number_of_tasks": number_of_tasks}) # Get the amount of blocks from the user # a selection is used, to minimize pronunciation errors. This way, the answer is compared to the options and the option that matches the answer the most is chosen. # For example, if mycroft thinks a user says 'free brooks', he will pick three blocks as answer. self.speak_dialog('blocks.amount.of.blocks') blocks = extract_number( self.ask_selection(['one block', 'two blocks', 'three blocks'], 'blocks.selection')) while not blocks: self.speak_dialog('skill.blocks.could.not.understand') blocks = extract_number( self.ask_selection(['one block', 'two blocks', 'three blocks'], 'skill.blocks.could.not.understand')) # If the user selects one block, Mycroft responds with the singular "block" if blocks == 1: amount_of_blocks = "1 block" # If the user selects multiple blocks, Mycroft responds with the plural "blocks" if blocks > 1: amount_of_blocks = "{} blocks".format(str(blocks)) # Get the current time to calculate the time when the user will be done in the future now = now_local() currenttime = now.strftime("%H:%M") # Calculate the time when the user is done based on the amount of blocks selected # Each block is 25 minutes and each break is 5 minutes minutes = blocks * 25 + (blocks - 1) * 5 futuretime = now + timedelta(minutes=minutes) futuretime = futuretime.strftime("%H:%M") # Respond to the user with the amount of blocks they have chosen, what the curren time is # and when their study session will be finished self.speak_dialog('blocks.confirmation', data={ 'currenttime': currenttime, 'amount_of_blocks': amount_of_blocks, 'futuretime': futuretime }) # The time.sleep() function takes an input of seconds # If you want the code to sleep for several minutes you should multiply the values with 60 # Currently everythting is in second for debugging purposes for i in range(blocks): time.sleep(25) if i < blocks - 1: self.speak_dialog('study.break.begin') time.sleep(5) self.speak_dialog('study.break.end') if i == blocks - 1: break self.speak_dialog('study.end')
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
def extract_datetime(text, anchorDate=None, lang=None, default_time=None): """ Extracts date and time information from a sentence. Parses many of the common ways that humans express dates and times, including relative dates like "5 days from today", "tomorrow', and "Tuesday". Vague terminology are given arbitrary values, like: - morning = 8 AM - afternoon = 3 PM - evening = 7 PM If a time isn't supplied or implied, the function defaults to 12 AM Args: text (str): the text to be interpreted anchorDate (:obj:`datetime`, optional): the date to be used for relative dating (for example, what does "tomorrow" mean?). Defaults to the current local date/time. lang (str): the BCP-47 code for the language to use, None uses default default_time (datetime.time): time to use if none was found in the input string. Returns: [:obj:`datetime`, :obj:`str`]: 'datetime' is the extracted date as a datetime object in the user's local timezone. 'leftover_string' is the original phrase with all date and time related keywords stripped out. See examples for further clarification Returns 'None' if no date or time related text is found. Examples: >>> extract_datetime( ... "What is the weather like the day after tomorrow?", ... datetime(2017, 06, 30, 00, 00) ... ) [datetime.datetime(2017, 7, 2, 0, 0), 'what is weather like'] >>> extract_datetime( ... "Set up an appointment 2 weeks from Sunday at 5 pm", ... datetime(2016, 02, 19, 00, 00) ... ) [datetime.datetime(2016, 3, 6, 17, 0), 'set up appointment'] >>> extract_datetime( ... "Set up an appointment", ... datetime(2016, 02, 19, 00, 00) ... ) None """ lang_code = get_primary_lang_code(lang) if not anchorDate: anchorDate = now_local() if lang_code == "en": return extract_datetime_en(text, anchorDate, default_time) elif lang_code == "es": return extract_datetime_es(text, anchorDate, default_time) elif lang_code == "pt": return extract_datetime_pt(text, anchorDate, default_time) elif lang_code == "it": return extract_datetime_it(text, anchorDate, default_time) elif lang_code == "fr": return extract_datetime_fr(text, anchorDate, default_time) elif lang_code == "sv": return extract_datetime_sv(text, anchorDate, default_time) elif lang_code == "de": return extract_datetime_de(text, anchorDate, default_time) elif lang_code == "da": return extract_datetime_da(text, anchorDate, default_time) # TODO: extract_datetime for other languages _log_unsupported_language(lang_code, ['en', 'es', 'pt', 'it', 'fr', 'sv', 'de', 'da']) return text
def remaining_time(self): return self.settings["duration"] - (now_local() - self.start_time).total_seconds()
def handle_start_timer(self, message): """ Common handler for start_timer intents """ utt = message.data["utterance"] #~~ GET TIMER DURATION secs, utt_remaining = self._extract_duration(utt) if secs and secs == 1: # prevent "set one timer" doing 1 sec timer utt_remaining = message.data["utterance"] if secs == None: # no duration found, request from user req_duration = self.get_response('ask.how.long') secs, _ = self._extract_duration(req_duration) if secs is None: return # user cancelled #~~ GET TIMER NAME if utt_remaining is not None and len(utt_remaining) > 0: timer_name = self._get_timer_name(utt_remaining) if timer_name: if self._check_duplicate_timer_name(timer_name): return # make another timer with a different name else: timer_name = None #~~ SHOULD IT BE AN ALARM? # TODO: add name of alarm if available? if secs >= 60 * 60 * 24: # 24 hours in seconds if self.ask_yesno("timer.too.long.alarm.instead") == 'yes': alarm_time = now_local() + timedelta(seconds=secs) phrase = self.translate( 'set.alarm', { 'date': alarm_time.strftime('%B %d %Y'), 'time': alarm_time.strftime('%I:%M%p') }) self.bus.emit( Message("recognizer_loop:utterance", { "utterances": [phrase], "lang": "en-us" })) return #~~ CREATE TIMER self.timer_index += 1 time_expires = datetime.now() + timedelta(seconds=secs) timer = { "name": timer_name, "index": self.timer_index, # keep track of ordinal until all timers of that name expire "ordinal": self._get_ordinal_of_new_timer(secs), "duration": secs, "expires": time_expires, "announced": False } self.active_timers.append(timer) self.log.debug("-------------TIMER-CREATED-------------") for key in timer: self.log.debug('creating timer: {}: {}'.format(key, timer[key])) self.log.debug("---------------------------------------") #~~ INFORM USER if timer['ordinal'] > 1: dialog = 'started.ordinal.timer' else: dialog = 'started.timer' if timer['name'] is not None: dialog += '.with.name' self.speak_dialog(dialog, data={ "duration": nice_duration(timer["duration"]), "name": timer["name"], "ordinal": self._get_speakable_ordinal(timer) }) #~~ CLEANUP self.pickle() wait_while_speaking() self.enable_intent("handle_mute_timer") # Start showing the remaining time on the faceplate self.update_display(None) # reset the mute flag with a new timer self.mute = False
def is_tomorrow(d): return d.date() == now_local().date() + timedelta(days=1)
def is_today(d): return d.date() == now_local().date()
import time from os.path import dirname, join from datetime import datetime, timedelta from mycroft import MycroftSkill, intent_file_handler from mycroft.util.parse import extract_datetime, normalize from mycroft.util.time import now_local from mycroft.util.format import nice_time, nice_date from mycroft.util.log import LOG from mycroft.util import play_wav from mycroft.messagebus.client import MessageBusClient REMINDER_PING = join(dirname(__file__), 'twoBeep.wav') MINUTES = 60 # seconds DEFAULT_TIME = now_local().replace(hour=8, minute=0, second=0) def deserialize(dt): return datetime.strptime(dt, '%Y%d%m-%H%M%S-%z') def serialize(dt): return dt.strftime('%Y%d%m-%H%M%S-%z') def is_today(d): return d.date() == now_local().date() def is_tomorrow(d): return d.date() == now_local().date() + timedelta(days=1)