Repository: MycroftAI/mycroft-core

Issue:
Alarm skill doesn't speak the date naturally
What I mean by this is if setting an alarm for 5 minutes, it reads the entire date (ie. "set an alarm for Thrusday, June 16th, at 04:05 pm") rather than simply saying the same thing in simpler terms (ie. "set an alarm for 5 minues"). And if the date is a day ahead I think it would be best that it says "Tomorrow at 4:05pm".



Discussion:
This should be a relatively simple change in the alarm skill.

This is actually behavior from the base `ScheduledCRUDSkill` class that @jdorleans created, which formats the time metadata as the full date. In order to change that, we'd have to change the base class, which would modify the behavior of all skills that inherit from that. That would be fine as long as we make sure that's what we want to do.


Resolving patch:
diff --git a/mycroft/skills/scheduled_skills.py b/mycroft/skills/scheduled_skills.py
--- a/mycroft/skills/scheduled_skills.py
+++ b/mycroft/skills/scheduled_skills.py
@@ -26,9 +26,12 @@
 from adapt.intent import IntentBuilder
 from mycroft.skills import time_rules
 from mycroft.skills.core import MycroftSkill
+from mycroft.util.log import getLogger
 
 __author__ = 'jdorleans'
 
+logger = getLogger(__name__)
+
 
 class ScheduledSkill(MycroftSkill):
     """
@@ -40,6 +43,9 @@ class ScheduledSkill(MycroftSkill):
     """
 
     DELTA_TIME = int((datetime.now() - datetime.utcnow()).total_seconds())
+    SECONDS_PER_DAY = 86400
+    SECONDS_PER_HOUR = 3600
+    SECONDS_PER_MINUTE = 60
 
     def __init__(self, name, emitter=None):
         super(ScheduledSkill, self).__init__(name, emitter)
@@ -73,7 +79,19 @@ def get_utc_time(self, sentence=''):
         return mktime(self.calendar.parse(sentence)[0]) - self.DELTA_TIME
 
     def get_formatted_time(self, timestamp):
-        return datetime.fromtimestamp(timestamp).strftime(
+        date = datetime.fromtimestamp(timestamp)
+        now = datetime.now()
+        diff = (date - now).total_seconds()
+        if diff <= self.SECONDS_PER_DAY:
+            hours, remainder = divmod(diff, self.SECONDS_PER_HOUR)
+            minutes, seconds = divmod(remainder, self.SECONDS_PER_MINUTE)
+            if hours:
+                return "%s hours and %s minutes from now" % \
+                       (int(hours), int(minutes))
+            else:
+                return "%s minutes and %s seconds from now" % \
+                       (int(minutes), int(seconds))
+        return date.strftime(
             self.config_core.get('time.format'))
 
     @abc.abstractmethod


Test patch:
diff --git a/test/skills/scheduled_skills.py b/test/skills/scheduled_skills.py
new file mode 100644
--- /dev/null
+++ b/test/skills/scheduled_skills.py
@@ -0,0 +1,31 @@
+from datetime import datetime, timedelta
+import unittest
+
+from mycroft.skills.scheduled_skills import ScheduledSkill
+from mycroft.util.log import getLogger
+
+__author__ = 'eward'
+
+logger = getLogger(__name__)
+
+
+class ScheduledSkillTest(unittest.TestCase):
+    skill = ScheduledSkill(name='ScheduledSkillTest')
+
+    def test_formatted_time_today_hours(self):
+        date = datetime.now() + timedelta(hours=2)
+        self.assertEquals(self.skill.
+                          get_formatted_time(float(date.strftime('%s'))),
+                          "1 hours and 59 minutes from now")
+
+    def test_formatted_time_today_min(self):
+        date = datetime.now() + timedelta(minutes=2)
+        self.assertEquals(self.skill.
+                          get_formatted_time(float(date.strftime('%s'))),
+                          "1 minutes and 59 seconds from now")
+
+    def test_formatted_time_days(self):
+        date = datetime.now() + timedelta(days=2)
+        self.assertEquals(self.skill.
+                          get_formatted_time(float(date.strftime('%s'))),
+                          date.strftime("%A, %B %d, %Y at %H:%M"))