diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php
index 6505c96c2fb..2cf6f0f9542 100644
--- a/admin/settings/appearance.php
+++ b/admin/settings/appearance.php
@@ -41,8 +41,11 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
     }
 
 
-    // calendar
+    // Calendar settings.
     $temp = new admin_settingpage('calendar', new lang_string('calendarsettings','admin'));
+
+    $temp->add(new admin_setting_configselect('calendartype', new lang_string('calendartype', 'admin'),
+        new lang_string('calendartype_desc', 'admin'), 'gregorian', \core_calendar\type_factory::get_list_of_calendar_types()));
     $temp->add(new admin_setting_special_adminseesall());
     //this is hacky because we do not want to include the stuff from calendar/lib.php
     $temp->add(new admin_setting_configselect('calendar_site_timeformat', new lang_string('pref_timeformat', 'calendar'),
diff --git a/auth/db/auth.php b/auth/db/auth.php
index d2087f71c88..3b80e2676a7 100644
--- a/auth/db/auth.php
+++ b/auth/db/auth.php
@@ -399,6 +399,9 @@ class auth_plugin_db extends auth_plugin_base {
                 if (empty($user->lang)) {
                     $user->lang = $CFG->lang;
                 }
+                if (empty($user->calendartype)) {
+                    $user->calendartype = $CFG->calendartype;
+                }
                 $user->timecreated = time();
                 $user->timemodified = $user->timecreated;
                 if ($collision = $DB->get_record_select('user', "username = :username AND mnethostid = :mnethostid AND auth <> :auth", array('username'=>$user->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'auth'=>$this->authtype), 'id,username,auth')) {
diff --git a/auth/email/auth.php b/auth/email/auth.php
index a670cfc36a5..b071e3252d9 100644
--- a/auth/email/auth.php
+++ b/auth/email/auth.php
@@ -90,6 +90,9 @@ class auth_plugin_email extends auth_plugin_base {
         require_once($CFG->dirroot.'/user/lib.php');
 
         $user->password = hash_internal_user_password($user->password);
+        if (empty($user->calendartype)) {
+            $user->calendartype = $CFG->calendartype;
+        }
 
         $user->id = user_create_user($user, false);
 
diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php
index a3fc3a84010..a847112c2e1 100644
--- a/auth/ldap/auth.php
+++ b/auth/ldap/auth.php
@@ -945,6 +945,9 @@ class auth_plugin_ldap extends auth_plugin_base {
                 if (empty($user->lang)) {
                     $user->lang = $CFG->lang;
                 }
+                if (empty($user->calendartype)) {
+                    $user->calendartype = $CFG->calendartype;
+                }
 
                 $id = user_create_user($user, false);
                 echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
diff --git a/lang/en/admin.php b/lang/en/admin.php
index a6bc7afd26f..7006d1a930c 100644
--- a/lang/en/admin.php
+++ b/lang/en/admin.php
@@ -95,6 +95,8 @@ $string['cachejs_help'] = 'Javascript caching and compression greatly improves p
 $string['cachetext'] = 'Text cache lifetime';
 $string['calendarexportsalt'] = 'Calendar export salt';
 $string['calendarsettings'] = 'Calendar';
+$string['calendartype'] = 'Calendar type';
+$string['calendartype_desc'] = 'Choose a default calendar type for the whole site. This setting can be overridden in the course settings or by users in their personal profile.';
 $string['calendar_weekend'] = 'Weekend days';
 $string['cannotdeletemodfilter'] = 'You cannot uninstall the \'{$a->filter}\' because it is part of the \'{$a->module}\' module.';
 $string['cannotuninstall'] = '{$a} can not be uninstalled.';
diff --git a/user/editlib.php b/user/editlib.php
index 6f886dacdbf..dde64e41b53 100644
--- a/user/editlib.php
+++ b/user/editlib.php
@@ -251,6 +251,7 @@ function useredit_shared_definition(&$mform, $editoroptions = null, $filemanager
     // We do not want to show this option unless there is more than one calendar type to display.
     if (count($calendartypes) > 1) {
         $mform->addElement('select', 'calendartype', get_string('preferredcalendar', 'calendar'), $calendartypes);
+        $mform->setDefault('calendartype', $CFG->calendartype);
     }
 
     if (!empty($CFG->allowuserthemes)) {
diff --git a/user/externallib.php b/user/externallib.php
index 6cc2e04a6dd..ae028aeac85 100644
--- a/user/externallib.php
+++ b/user/externallib.php
@@ -59,6 +59,7 @@ class core_user_external extends external_api {
                             'auth'                => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_DEFAULT, 'manual', NULL_NOT_ALLOWED),
                             'idnumber'            => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''),
                             'lang'                => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_DEFAULT, $CFG->lang, NULL_NOT_ALLOWED),
+                            'calendartype'        => new external_value(PARAM_PLUGIN, 'Calendar type such as "gregorian", must exist on server', VALUE_DEFAULT, $CFG->calendartype, VALUE_OPTIONAL),
                             'theme'               => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
                             'timezone'            => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
                             'mailformat'          => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
@@ -273,7 +274,6 @@ class core_user_external extends external_api {
      * @since Moodle 2.2
      */
     public static function update_users_parameters() {
-        global $CFG;
         return new external_function_parameters(
             array(
                 'users' => new external_multiple_structure(
@@ -288,6 +288,7 @@ class core_user_external extends external_api {
                             'auth'                => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED),
                             'idnumber'            => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL),
                             'lang'                => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED),
+                            'calendartype'        => new external_value(PARAM_PLUGIN, 'Calendar type such as "gregorian", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED),
                             'theme'               => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
                             'timezone'            => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
                             'mailformat'          => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
@@ -893,6 +894,7 @@ class core_user_external extends external_api {
                     'auth'        => new external_value(PARAM_PLUGIN, 'Auth plugins include manual, ldap, imap, etc', VALUE_OPTIONAL),
                     'confirmed'   => new external_value(PARAM_INT, 'Active user: 1 if confirmed, 0 otherwise', VALUE_OPTIONAL),
                     'lang'        => new external_value(PARAM_SAFEDIR, 'Language code such as "en", must exist on server', VALUE_OPTIONAL),
+                    'calendartype' => new external_value(PARAM_PLUGIN, 'Calendar type such as "gregorian", must exist on server', VALUE_OPTIONAL),
                     'theme'       => new external_value(PARAM_PLUGIN, 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL),
                     'timezone'    => new external_value(PARAM_TIMEZONE, 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL),
                     'mailformat'  => new external_value(PARAM_INT, 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL),
diff --git a/user/lib.php b/user/lib.php
index 7ab6c0d2ab5..3e3b75456e2 100644
--- a/user/lib.php
+++ b/user/lib.php
@@ -33,11 +33,11 @@
  * @return int id of the newly created user
  */
 function user_create_user($user, $updatepassword = true) {
-    global $DB;
+    global $CFG, $DB;
 
     // Set the timecreate field to the current time.
     if (!is_object($user)) {
-            $user = (object)$user;
+        $user = (object) $user;
     }
 
     // Check username.
@@ -61,6 +61,16 @@ function user_create_user($user, $updatepassword = true) {
         unset($user->password);
     }
 
+    // Make sure calendartype, if set, is valid.
+    if (!empty($user->calendartype)) {
+        $availablecalendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
+        if (empty($availablecalendartypes[$user->calendartype])) {
+            $user->calendartype = $CFG->calendartype;
+        }
+    } else {
+        $user->calendartype = $CFG->calendartype;
+    }
+
     $user->timecreated = time();
     $user->timemodified = $user->timecreated;
 
@@ -101,7 +111,7 @@ function user_update_user($user, $updatepassword = true) {
 
     // set the timecreate field to the current time
     if (!is_object($user)) {
-            $user = (object)$user;
+        $user = (object) $user;
     }
 
     //check username
@@ -127,6 +137,18 @@ function user_update_user($user, $updatepassword = true) {
         unset($user->password);
     }
 
+    // Make sure calendartype, if set, is valid.
+    if (!empty($user->calendartype)) {
+        $availablecalendartypes = \core_calendar\type_factory::get_list_of_calendar_types();
+        // If it doesn't exist, then unset this value, we do not want to update the user's value.
+        if (empty($availablecalendartypes[$user->calendartype])) {
+            unset($user->calendartype);
+        }
+    } else {
+        // Unset this variable, must be an empty string, which we do not want to update the calendartype to.
+        unset($user->calendartype);
+    }
+
     $user->timemodified = time();
     $DB->update_record('user', $user);