diff --git a/library/system/cron b/library/system/cron
index 633bccba8ad..fee6a2a1bfc 100644
--- a/library/system/cron
+++ b/library/system/cron
@@ -3,6 +3,7 @@
 #
 # (c) 2012, Dane Summers <dsummers@pinedesk.biz>
 # (c) 2013, Mike Grozak  <mike.grozak@gmail.com>
+# (c) 2013, Patrick Callahan <pmc@patrickcallahan.com>
 #
 # This file is part of Ansible
 #
@@ -18,17 +19,20 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
-
+#
 # Cron Plugin: The goal of this plugin is to provide an indempotent method for
 # setting up cron jobs on a host. The script will play well with other manually
 # entered crons. Each cron job entered will be preceded with a comment
 # describing the job so that it can be found later, which is required to be
 # present in order for this plugin to find/modify the job.
+#
+# This module is based on python-crontab by Martin Owens.
+#
 
 DOCUMENTATION = """
 ---
 module: cron
-short_description: Manage crontab entries.
+short_description: Manage cron.d and crontab entries.
 description:
   - Use this module to manage crontab entries. This module allows you to create named
     crontab entries, update, or delete them.
@@ -40,80 +44,76 @@ options:
   name:
     description:
       - Description of a crontab entry.
-    required: true
-    default:
-    aliases: []
+    required: false
+    default: null
   user:
     description:
       - The specific user who's crontab should be modified.
     required: false
     default: root
-    aliases: []
   job:
     description:
-      - The command to execute.
-      - Required if state=present.
+      - The command to execute. Required if state=present.
     required: false
-    default: 
-    aliases: []
+    default: null
   state:
     description:
-      - Whether to ensure the job is present or absent.  
+      - Whether to ensure the job is present or absent.
     required: false
     default: present
-    aliases: []
+    choices: [ "present", "absent" ]
   cron_file:
     description:
-      - If specified, uses this file in cron.d versus in the main crontab
+      - If specified, uses this file in cron.d instead of an individual user's crontab.
     required: false
-    default:
-    aliases: []
+    default: null
   backup:
     description:
-      - If set, then create a backup of the crontab before it is modified.
-      - The location of the backup is returned in the C(backup) variable by this module.
+      - If set, create a backup of the crontab before it is modified.
+        The location of the backup is returned in the C(backup) variable by this module.
     required: false
     default: false
-    aliases: []
   minute:
     description:
       - Minute when the job should run ( 0-59, *, */2, etc )
     required: false
     default: "*"
-    aliases: []
   hour:
     description:
       - Hour when the job should run ( 0-23, *, */2, etc )
     required: false
     default: "*"
-    aliases: []
   day:
     description:
       - Day of the month the job should run ( 1-31, *, */2, etc )
     required: false
     default: "*"
-    aliases: []
+    aliases: [ "dom" ]
   month:
     description:
       - Month of the year the job should run ( 1-12, *, */2, etc )
     required: false
     default: "*"
-    aliases: []
   weekday:
     description:
-      - Day of the week that the job should run ( 0-7 for Sunday - Saturday, or mon, tue, * etc )
+      - Day of the week that the job should run ( 0-7 for Sunday - Saturday, *, etc )
     required: false
     default: "*"
-    aliases: []
-
+    aliases: [ "dow" ]
   reboot:
     description:
-      - If the job should be run at reboot, will ignore minute, hour, day, and month settings in favour of C(@reboot)
+      - If the job should be run at reboot. This option is deprecated. Users should use special_time.
     version_added: "1.0"
     required: false
     default: "no"
     choices: [ "yes", "no" ]
-    aliases: []
+  special_time:
+    description:
+      - Special time specification nickname.
+    version_added: "1.3"
+    required: false
+    default: null
+    choices: [ "reboot", "yearly", "annually", "monthly", "weekly", "daily", "hourly" ]
 requirements:
   - cron
 author: Dane Summers
@@ -127,124 +127,258 @@ EXAMPLES = '''
 
 # Ensure an old job is no longer present. Removes any job that is prefixed
 # by "#Ansible: an old job" from the crontab
-- cron: name="an old job" cron job="/some/dir/job.sh" state=absent
+- cron: name="an old job" state=absent
 
 # Creates an entry like "@reboot /some/job.sh"
-- cron: name="a job for reboot" reboot=yes job="/some/job.sh"
+- cron: name="a job for reboot" special_time=reboot job="/some/job.sh"
 
+# Creates a cron file under /etc/cron.d
 - cron: name="yum autoupdate" weekday="2" minute=0 hour=12
         user="root" job="YUMINTERACTIVE=0 /usr/sbin/yum-autoupdate"
         cron_file=ansible_yum-autoupdate
+
+# Removes a cron file from under /etc/cron.d
+- cron: cron_file=ansible_yum-autoupdate state=absent
 '''
 
+import os
 import re
 import tempfile
-import os
 
-def get_jobs_file(module, user, tmpfile, cron_file):
-    if cron_file:
-        cmd = "cp -fp /etc/cron.d/%s %s" % (cron_file, tmpfile)
-    else:
-        cmd = "crontab -l %s > %s" % (user,tmpfile)
-    
-    return module.run_command(cmd)
+CRONCMD = "/usr/bin/crontab"
 
-def install_jobs(module, user, tmpfile, cron_file):
-    if cron_file:
-        cron_file = '/etc/cron.d/%s' % cron_file
-        module.atomic_move(tmpfile, cron_file)
-    else:
-        cmd = "crontab %s %s" % (user, tmpfile)
-        return module.run_command(cmd)
+class CronTabError(Exception):
+    pass
 
-def get_jobs(tmpfile):
-    lines = open(tmpfile).read().splitlines()
-    comment = None
-    jobs = []
-    for l in lines:
-        if comment is not None:
-            jobs.append([comment,l])
-            comment = None
-        elif re.match( r'#Ansible: ',l):
-            comment = re.sub( r'#Ansible: ', '', l)
-    return jobs
+class CronTab(object):
+    """
+        CronTab object to write time based crontab file
 
-def find_job(name,tmpfile):
-    jobs = get_jobs(tmpfile)
-    for j in jobs:
-        if j[0] == name:
-            return j
-    return []
+        user      - the user of the crontab (defaults to root)
+        cron_file - a cron file under /etc/cron.d
+    """
+    def __init__(self, module, user=None, cron_file=None):
+        self.module    = module
+        self.user      = user
+        self.root      = (os.getuid() == 0)
+        self.lines     = None
+        self.ansible   = "#Ansible: "
 
-def add_job(module,name,job,tmpfile):
-    f = open(tmpfile, 'a')
-    f.write("#Ansible: %s\n%s\n" % (name, job))
-    f.close()
+        # select whether we dump additional debug info through syslog
+        self.syslogging = False
 
-def update_job(name,job,tmpfile):
-    return _update_job(name,job,tmpfile,do_add_job)
-
-def do_add_job(lines, comment, job):
-    lines.append(comment)
-    lines.append(job)
-
-def remove_job(name,tmpfile):
-    return _update_job(name, "", tmpfile, do_remove_job)
-
-def do_remove_job(lines,comment,job):
-    return None
-
-def remove_job_file(cron_file):
-    fname = "/etc/cron.d/%s" % (cron_file)
-    os.unlink(fname)
-
-def _update_job(name,job,tmpfile,addlinesfunction):
-    ansiblename = "#Ansible: %s" % (name)
-    f = open(tmpfile)
-    lines = f.read().splitlines()
-    f.close()
-    newlines = []
-    comment = None
-    for l in lines:
-        if comment is not None:
-            addlinesfunction(newlines,comment,job)
-            comment = None
-        elif l == ansiblename:
-            comment = l
-        else:
-            newlines.append(l)
-    f = open(tmpfile, 'w')
-    for l in newlines:
-        f.write(l)
-        f.write('\n')
-    f.close()
-
-    if len(newlines) == 0:
-        return True
-    else:
-        return False # TODO add some more error testing 
-
-def get_cron_job(minute,hour,day,month,weekday,job,user,cron_file,reboot):
-    if reboot:
         if cron_file:
-            return "@reboot %s %s" % (user, job)
+            self.cron_file = '/etc/cron.d/%s' % cron_file
         else:
-            return "@reboot %s" % (job)
-    else:
-        if cron_file:
-            return "%s %s %s %s %s %s %s" % (minute,hour,day,month,weekday,user,job)
-        else:
-            return "%s %s %s %s %s %s" % (minute,hour,day,month,weekday,job)
+            self.cron_file = None
 
-    return None
+        self.read()
+
+    def read(self):
+        # Read in the crontab from the system
+        self.lines = []
+        if self.cron_file:
+            # read the cronfile
+            try:
+                f = open(self.cron_file, 'r')
+                self.lines = f.read().splitlines()
+                f.close()
+            except IOError as e:
+                # cron file does not exist
+                return
+            except:
+                raise CronTabError("Unexpected error:", sys.exc_info()[0])
+        else:
+            (rc, out, err) = self.module.run_command(self._read_user_execute())
+
+            if rc != 0 and rc != 1: # 1 can mean that there are no jobs.
+                raise CronTabError("Unable to read crontab")
+
+            lines = out.splitlines()
+            count = 0
+            for l in lines:
+                if count > 2 or (not re.match( r'# DO NOT EDIT THIS FILE - edit the master and reinstall.', l) and
+                                 not re.match( r'# \(/tmp/.*installed on.*\)', l) and
+                                 not re.match( r'# \(.*version.*\)', l)):
+                    self.lines.append(l)
+                count += 1
+
+    def log_message(self, message):
+        if self.syslogging:
+            syslog.syslog(syslog.LOG_NOTICE, 'ansible: "%s"' % message)
+
+    def is_empty(self):
+        if len(self.lines) == 0:
+            return True
+        else:
+            return False
+
+    def write(self, backup_file=None):
+        """
+        Write the crontab to the system. Saves all information.
+        """
+        if backup_file:
+            fileh = open(backup_file, 'w')
+        elif self.cron_file:
+            fileh = open(self.cron_file, 'w')
+        else:
+            filed, path = tempfile.mkstemp(prefix='crontab')
+            fileh = os.fdopen(filed, 'w')
+
+        fileh.write(self.render())
+        fileh.close()
+
+        # return if making a backup
+        if backup_file:
+            return
+
+        # Add the entire crontab back to the user crontab
+        if not self.cron_file:
+            # os.system(self._write_execute(path))
+            (rc, out, err) = self.module.run_command(self._write_execute(path))
+            os.unlink(path)
+
+            if rc != 0:
+                self.module.fail_json(msg=err)
+
+    def add_job(self, name, job):
+        # Add the comment
+        self.lines.append("%s%s" % (self.ansible, name))
+
+        # Add the job
+        self.lines.append("%s" % (job))
+
+    def update_job(self, name, job):
+        return self._update_job(name, job, self.do_add_job)
+
+    def do_add_job(self, lines, comment, job):
+        lines.append(comment)
+
+        lines.append("%s" % (job))
+
+    def remove_job(self, name):
+        return self._update_job(name, "", self.do_remove_job)
+
+    def do_remove_job(self, lines, comment, job):
+        return None
+
+    def remove_job_file(self):
+        try:
+            os.unlink(self.cron_file)
+        except OSError as e:
+            # cron file does not exist
+            return
+        except:
+            raise CronTabError("Unexpected error:", sys.exc_info()[0])
+
+    def find_job(self, name):
+        comment = None
+        for l in self.lines:
+            if comment is not None:
+                if comment == name:
+                    return [comment, l]
+                else:
+                    comment = None
+            elif re.match( r'%s' % self.ansible, l):
+                comment = re.sub( r'%s' % self.ansible, '', l)
+
+        return []
+
+    def get_cron_job(self,minute,hour,day,month,weekday,job,special):
+        if special:
+            if self.cron_file:
+                return "@%s %s %s" % (special, self.user, job)
+            else:
+                return "@%s %s" % (special, job)
+        else:
+            if self.cron_file:
+                return "%s %s %s %s %s %s %s" % (minute,hour,day,month,weekday,self.user,job)
+            else:
+                return "%s %s %s %s %s %s" % (minute,hour,day,month,weekday,job)
+
+        return None
+
+    def get_jobnames(self):
+        jobnames = []
+
+        for l in self.lines:
+            if re.match( r'%s' % self.ansible, l):
+                jobnames.append(re.sub( r'%s' % self.ansible, '', l))
+
+        return jobnames
+
+    def _update_job(self, name, job, addlinesfunction):
+        ansiblename = "%s%s" % (self.ansible, name)
+        newlines = []
+        comment = None
+
+        for l in self.lines:
+            if comment is not None:
+                addlinesfunction(newlines, comment, job)
+                comment = None
+            elif l == ansiblename:
+                comment = l
+            else:
+                newlines.append(l)
+
+        self.lines = newlines
+
+        if len(newlines) == 0:
+            return True
+        else:
+            return False # TODO add some more error testing
+
+    def render(self):
+        """
+        Render this crontab as it would be in the crontab.
+        """
+        crons = []
+        for cron in self.lines:
+            crons.append(cron)
+
+        result = '\n'.join(crons)
+        if result and result[-1] not in ['\n', '\r']:
+            result += '\n'
+        return result
+
+    def _read_file_execute(self):
+        """
+        Returns the command line for reading a crontab
+        """
+        return "%s -l%s" % (CRONCMD, self._user_execute())
+
+    def _read_user_execute(self):
+        """
+        Returns the command line for reading a crontab
+        """
+        return "%s -l %s" % (CRONCMD, self._user_execute())
+
+    def _write_execute(self, path):
+        """
+        Return the command line for writing a crontab
+        """
+        return "%s %s %s" % (CRONCMD, path, self._user_execute())
+
+    def _user_execute(self):
+        """
+        User command switches to append to the read and write commands.
+        """
+        if self.user:
+            return "%s %s" % (' -u ', str(self.user))
+        return ''
+
+#==================================================
 
 def main():
     # The following example playbooks:
-    # - action: cron name="check dirs" hour="5,2" job="ls -alh > /dev/null"
+    #
+    # - cron: name="check dirs" hour="5,2" job="ls -alh > /dev/null"
+    #
     # - name: do the job
-    #   action: name="do the job" cron hour="5,2" job="/some/dir/job.sh"
+    #   cron: name="do the job" hour="5,2" job="/some/dir/job.sh"
+    #
     # - name: no job
-    #   action: name="an old job" cron job="/some/dir/job.sh" state=absent
+    #   cron: name="an old job" state=absent
     #
     # Would produce:
     # # Ansible: check dirs
@@ -252,19 +386,9 @@ def main():
     # # Ansible: do the job
     # * * 5,2 * * /some/dir/job.sh
 
-    # Function:
-    # 1. dump the existing cron:
-    #    crontab -l -u <user> > /tmp/tmpfile
-    # 2. search for comment "^# Ansible: <name>" followed by a cron.
-    # 3. if absent: remove if present (and say modified), otherwise return with no mod.
-    # 4. if present: if the same return no mod, if not present add (and say mod), if different add (and say mod)
-    # 5. Install new cron (if mod):
-    #    crontab -u <user> /tmp/tmpfile
-    # 6. return mod
-
     module = AnsibleModule(
         argument_spec = dict(
-            name=dict(required=True),
+            name=dict(required=False),
             user=dict(required=False),
             job=dict(required=False),
             cron_file=dict(required=False),
@@ -272,99 +396,113 @@ def main():
             backup=dict(default=False, type='bool'),
             minute=dict(default='*'),
             hour=dict(default='*'),
-            day=dict(default='*'),
+            day=dict(aliases=['dom'], default='*'),
             month=dict(default='*'),
-            weekday=dict(default='*'),
-            reboot=dict(required=False, default=False, type='bool')
-        )
+            weekday=dict(aliases=['dow'], default='*'),
+            reboot=dict(required=False, default=False, type='bool'),
+            special_time=dict(required=False,
+                              default=None,
+                              choices=["reboot", "yearly", "annually", "monthly", "weekly", "daily", "hourly"],
+                              type='str')
+        ),
+        supports_check_mode = False,
     )
 
-    backup     = module.params['backup']
-    name       = module.params['name']
-    user       = module.params['user']
-    job        = module.params['job']
-    cron_file  = module.params['cron_file']
-    minute     = module.params['minute']
-    hour       = module.params['hour']
-    day        = module.params['day']
-    month      = module.params['month']
-    weekday    = module.params['weekday']
-    reboot     = module.params['reboot']
-    state      = module.params['state']
-    do_install = module.params['state'] == 'present'
-    changed    = False
+    name         = module.params['name']
+    user         = module.params['user']
+    job          = module.params['job']
+    cron_file    = module.params['cron_file']
+    state        = module.params['state']
+    backup       = module.params['backup']
+    minute       = module.params['minute']
+    hour         = module.params['hour']
+    day          = module.params['day']
+    month        = module.params['month']
+    weekday      = module.params['weekday']
+    reboot       = module.params['reboot']
+    special_time = module.params['special_time']
+    do_install   = state == 'present'
 
-    if reboot and (True in [(x != '*') for x in [minute, hour, day, month, weekday]]):
-        module.fail_json(msg="You must specify either reboot=True or any of minute, hour, day, month, weekday")
+    changed      = False
+    res_args     = dict()
 
-    if cron_file:
+    crontab = CronTab(module, user, cron_file)
+
+    if crontab.syslogging:
+        syslog.openlog('ansible-%s' % os.path.basename(__file__))
+        syslog.syslog(syslog.LOG_NOTICE, 'cron instantiated - name: "%s"' % name)
+
+    # --- user input validation ---
+
+    if (special_time or reboot) and \
+       (True in [(x != '*') for x in [minute, hour, day, month, weekday]]):
+        module.fail_json(msg="You must specify time and date fields or special time.")
+
+    if cron_file and do_install:
         if not user:
             module.fail_json(msg="To use file=... parameter you must specify user=... as well")
-    else:
-        if not user:
-            user = ""
-        else:
-            user = "-u %s" % (user)
 
-    job = get_cron_job(minute,hour,day,month,weekday,job,user,cron_file,reboot)
-    rc, out, err, rm, status = (0, None, None, None, None)
+    if reboot and special_time:
+        module.fail_json(msg="reboot and special_time are mutually exclusive")
+
+    if name is None and do_install:
+        module.fail_json(msg="You must specify 'name' to install a new cron job")
+
     if job is None and do_install:
         module.fail_json(msg="You must specify 'job' to install a new cron job")
 
-    tmpfile = tempfile.NamedTemporaryFile()
-    (rc, out, err) = get_jobs_file(module,user,tmpfile.name, cron_file)
+    if reboot:
+        if special_time:
+            module.fail_json(msg="reboot and special_time are mutually exclusive")
+        else:
+            special_time = "reboot"
 
-    if rc != 0 and rc != 1: # 1 can mean that there are no jobs.
-        module.fail_json(msg=err)
+    # if requested make a backup before making a change
+    if backup:
+        (backuph, backup_file) = tempfile.mkstemp(prefix='crontab')
+        crontab.write(backup_file)
 
-    (handle,backupfile) = tempfile.mkstemp(prefix='crontab')
-    (rc, out, err) = get_jobs_file(module,user,backupfile, cron_file)
-    if rc != 0 and rc != 1:
-        module.fail_json(msg=err)
+    if crontab.cron_file and not do_install:
+        crontab.remove_job_file()
+        changed = True
+        module.exit_json(changed=changed,cron_file=cron_file,state=state)
+
+    job = crontab.get_cron_job(minute, hour, day, month, weekday, job, special_time)
+    old_job = crontab.find_job(name)
 
-    old_job = find_job(name,backupfile)
     if do_install:
         if len(old_job) == 0:
-            add_job(module,name,job,tmpfile.name)
+            crontab.add_job(name, job)
             changed = True
         if len(old_job) > 0 and old_job[1] != job:
-            update_job(name,job,tmpfile.name)
+            crontab.update_job(name, job)
             changed = True
     else:
         if len(old_job) > 0:
-            # if rm is true after the next line, file will be deleted afterwards
-            rm = remove_job(name,tmpfile.name)
+            crontab.remove_job(name)
             changed = True
-        else:
-            # there is no old_jobs for deletion - we should leave everything
-            # as is. If the file is empty, it will be removed later
-            tmpfile.close()
-            # the file created by mks should be deleted explicitly
-            os.unlink(backupfile)
-            module.exit_json(changed=changed,cron_file=cron_file,state=state)
+
+    res_args = dict(
+        jobs = crontab.get_jobnames(), changed = changed
+    )
 
     if changed:
-        # If the file is empty - remove it
-        if rm and cron_file:
-            remove_job_file(cron_file)
+        crontab.write()
+
+    # retain the backup only if crontab or cron file have changed
+    if backup:
+        if changed:
+            res_args['backup_file'] = backup_file
         else:
-            if backup:
-                module.backup_local(backupfile)
-            (rc, out, err) = install_jobs(module,user,tmpfile.name, cron_file)
-            if (rc != 0):
-                module.fail_json(msg=err)
+            os.unlink(backup_file)
 
-    # get the list of jobs in file
-    jobnames = []
-    for j in get_jobs(tmpfile.name):
-        jobnames.append(j[0])
-    tmpfile.close()
+    if cron_file:
+        res_args['cron_file'] = cron_file
 
-    if not backup:
-        os.unlink(backupfile)
-        module.exit_json(changed=changed,jobs=jobnames)
-    else:
-        module.exit_json(changed=changed,jobs=jobnames,backup=backupfile)
+    module.exit_json(**res_args)
+
+    # --- should never get here
+    module.exit_json(msg="Unable to execute cron task.")
 
 # include magic from lib/ansible/module_common.py
 #<<INCLUDE_ANSIBLE_MODULE_COMMON>>