diff --git a/3rdparty b/3rdparty
index f6d7a519e4dca5189963abb15e5c9858b03bf98d..94179d9d70b6be43ff4251941034cd2735d10f4e 160000
--- a/3rdparty
+++ b/3rdparty
@@ -1 +1 @@
-Subproject commit f6d7a519e4dca5189963abb15e5c9858b03bf98d
+Subproject commit 94179d9d70b6be43ff4251941034cd2735d10f4e
diff --git a/core/js/config.php b/core/js/config.php
index 6994f2ed8a210065ebba5e9614737766f0e52ff2..52405725f23286097b6a6a1d91f07fb806417d22 100644
--- a/core/js/config.php
+++ b/core/js/config.php
@@ -39,7 +39,7 @@ $array = array(
 	"oc_isadmin" => OC_User::isAdminUser(OC_User::getUser()) ? 'true' : 'false',
 	"oc_webroot" => "\"".OC::$WEBROOT."\"",
 	"oc_appswebroots" =>  str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
-	"datepickerFormatDate" => json_encode($l->l('jsdate', 'jsdate')),
+	"datepickerFormatDate" => json_encode($l->getDateFormat()),
 	"dayNames" =>  json_encode(
 		array(
 			(string)$l->t('Sunday'),
@@ -67,7 +67,7 @@ $array = array(
 			(string)$l->t('December')
 		)
 	),
-	"firstDay" => json_encode($l->l('firstday', 'firstday')) ,
+	"firstDay" => json_encode($l->getFirstWeekDay()) ,
 	"oc_config" => json_encode(
 		array(
 			'session_lifetime'	=> min(\OCP\Config::getSystemValue('session_lifetime', ini_get('session.gc_maxlifetime')), ini_get('session.gc_maxlifetime')),
diff --git a/core/l10n/l10n-de.php b/core/l10n/l10n-de.php
deleted file mode 100644
index 77d35af493675c1b31eda4db7bf9b5e143aeff4b..0000000000000000000000000000000000000000
--- a/core/l10n/l10n-de.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-$LOCALIZATIONS = array(
-	'jsdate' => 'dd.mm.yy',
-	'date' => '%d.%m.%Y',
-	'datetime' => '%d.%m.%Y %H:%M:%S',
-	'time' => '%H:%M:%S',
-	'firstday' => 0 );
diff --git a/core/l10n/l10n-en.php b/core/l10n/l10n-en.php
deleted file mode 100644
index 9ee748bee23584d3cd6e442e52b56007431b29de..0000000000000000000000000000000000000000
--- a/core/l10n/l10n-en.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-$LOCALIZATIONS = array(
-	'jsdate' => 'MM d, yy',
-	'date' => '%B %e, %Y',
-	'datetime' => '%B %e, %Y %H:%M',
-	'time' => '%H:%M:%S',
-	'firstday' => 0 );
diff --git a/core/l10n/l10n-es.php b/core/l10n/l10n-es.php
deleted file mode 100644
index 13db2ec5d4c7b65b420fda570c6f174b03a451d9..0000000000000000000000000000000000000000
--- a/core/l10n/l10n-es.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-$LOCALIZATIONS = array(
-	'jsdate' => "d 'de' MM 'de' yy",
-	'date' => '%e de %B de %Y',
-	'datetime' => '%e de %B de %Y %H:%M',
-	'time' => '%H:%M:%S',
-	'firstday' => 1 );
diff --git a/lib/private/l10n.php b/lib/private/l10n.php
index 57886a796cd15ae4b72cebc9305ef96edf013ebc..0b20eafea32c8622305078937cb5f7cc7cae21b0 100644
--- a/lib/private/l10n.php
+++ b/lib/private/l10n.php
@@ -61,16 +61,6 @@ class OC_L10N implements \OCP\IL10N {
 	 */
 	private $plural_form_function = null;
 
-	/**
-	 * Localization
-	 */
-	private $localizations = array(
-		'jsdate' => 'dd.mm.yy',
-		'date' => '%d.%m.%Y',
-		'datetime' => '%d.%m.%Y %H:%M:%S',
-		'time' => '%H:%M:%S',
-		'firstday' => 0);
-
 	/**
 	 * get an L10N instance
 	 * @param string $app
@@ -126,13 +116,10 @@ class OC_L10N implements \OCP\IL10N {
 
 		// Use cache if possible
 		if(array_key_exists($app.'::'.$lang, self::$cache)) {
-
 			$this->translations = self::$cache[$app.'::'.$lang]['t'];
-			$this->localizations = self::$cache[$app.'::'.$lang]['l'];
-		}
-		else{
+		} else{
 			$i18ndir = self::findI18nDir($app);
-			// Localization is in /l10n, Texts are in $i18ndir
+			// Texts are in $i18ndir
 			// (Just no need to define date/time format etc. twice)
 			if((OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')
 				|| OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/lib/l10n/')
@@ -162,16 +149,7 @@ class OC_L10N implements \OCP\IL10N {
 				}
 			}
 
-			if(file_exists(OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php') && OC_Helper::isSubDirectory(OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')) {
-				// Include the file, save the data from $CONFIG
-				include OC::$SERVERROOT.'/core/l10n/l10n-'.$lang.'.php';
-				if(isset($LOCALIZATIONS) && is_array($LOCALIZATIONS)) {
-					$this->localizations = array_merge($this->localizations, $LOCALIZATIONS);
-				}
-			}
-
 			self::$cache[$app.'::'.$lang]['t'] = $this->translations;
-			self::$cache[$app.'::'.$lang]['l'] = $this->localizations;
 		}
 	}
 
@@ -312,17 +290,6 @@ class OC_L10N implements \OCP\IL10N {
 		return $this->plural_form_function;
 	}
 
-	/**
-	 * get localizations
-	 * @return array Fetch all localizations
-	 *
-	 * Returns an associative array with all localizations
-	 */
-	public function getLocalizations() {
-		$this->init();
-		return $this->localizations;
-	}
-
 	/**
 	 * Localization
 	 * @param string $type Type of localization
@@ -334,45 +301,45 @@ class OC_L10N implements \OCP\IL10N {
 	 * Implemented types:
 	 *  - date
 	 *    - Creates a date
-	 *    - l10n-field: date
 	 *    - params: timestamp (int/string)
 	 *  - datetime
 	 *    - Creates date and time
-	 *    - l10n-field: datetime
 	 *    - params: timestamp (int/string)
 	 *  - time
 	 *    - Creates a time
-	 *    - l10n-field: time
 	 *    - params: timestamp (int/string)
 	 */
-	public function l($type, $data) {
+	public function l($type, $data, $options = array()) {
+		if ($type === 'firstday') {
+			return $this->getFirstWeekDay();
+		}
+		if ($type === 'jsdate') {
+			return $this->getDateFormat();
+		}
+
 		$this->init();
+		$value = new DateTime();
+		if($data instanceof DateTime) {
+			$value = $data;
+		} elseif(is_string($data) && !is_numeric($data)) {
+			$data = strtotime($data);
+			$value->setTimestamp($data);
+		} else {
+			$value->setTimestamp($data);
+		}
+		$locale = self::findLanguage();
+		$options = array_merge(array('width' => 'long'), $options);
+		$width = $options['width'];
 		switch($type) {
-			// If you add something don't forget to add it to $localizations
-			// at the top of the page
 			case 'date':
+				return Punic\Calendar::formatDate($value, $width, $locale);
+				break;
 			case 'datetime':
+				return Punic\Calendar::formatDatetime($value, $width, $locale);
+				break;
 			case 'time':
-				if($data instanceof DateTime) {
-					$data = $data->getTimestamp();
-				} elseif(is_string($data) && !is_numeric($data)) {
-					$data = strtotime($data);
-				}
-				$locales = array(self::findLanguage());
-				if (strlen($locales[0]) == 2) {
-					$locales[] = $locales[0].'_'.strtoupper($locales[0]);
-				}
-				setlocale(LC_TIME, $locales);
-				$format = $this->localizations[$type];
-				// Check for Windows to find and replace the %e modifier correctly
-				if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
-					$format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format);
-				}
-				return strftime($format, $data);
+				return Punic\Calendar::formatTime($value, $width, $locale);
 				break;
-			case 'firstday':
-			case 'jsdate':
-				return $this->localizations[$type];
 			default:
 				return false;
 		}
@@ -495,7 +462,7 @@ class OC_L10N implements \OCP\IL10N {
 	/**
 	 * find the l10n directory
 	 * @param string $app App that needs to be translated
-	 * @return directory
+	 * @return string directory
 	 */
 	protected static function findI18nDir($app) {
 		// find the i18n dir
@@ -547,4 +514,21 @@ class OC_L10N implements \OCP\IL10N {
 		}
 		return false;
 	}
+
+	/**
+	 * @return string
+	 * @throws \Punic\Exception\ValueNotInList
+	 */
+	public function getDateFormat() {
+		$locale = self::findLanguage();
+		return Punic\Calendar::getDateFormat('short', $locale);
+	}
+
+	/**
+	 * @return int
+	 */
+	public function getFirstWeekDay() {
+		$locale = self::findLanguage();
+		return Punic\Calendar::getFirstWeekday($locale);
+	}
 }
diff --git a/tests/lib/l10n.php b/tests/lib/l10n.php
index 5ddf2290c352f4dc9ecfe927c812e06b4b8cbf08..a97fa22f05c6939f2da636267a3517e1fbd3cf6e 100644
--- a/tests/lib/l10n.php
+++ b/tests/lib/l10n.php
@@ -52,17 +52,67 @@ class Test_L10n extends PHPUnit_Framework_TestCase {
 		$this->assertEquals('5 oken', (string)$l->n('%n window', '%n windows', 5));
 	}
 
+	public function localizationDataProvider() {
+		return array(
+			// timestamp as string
+			array('February 13, 2009 at 11:31:30 PM GMT+0', 'en', 'datetime', '1234567890'),
+			array('13. Februar 2009 um 23:31:30 GMT+0', 'de', 'datetime', '1234567890'),
+			array('February 13, 2009', 'en', 'date', '1234567890'),
+			array('13. Februar 2009', 'de', 'date', '1234567890'),
+			array('11:31:30 PM GMT+0', 'en', 'time', '1234567890'),
+			array('23:31:30 GMT+0', 'de', 'time', '1234567890'),
+
+			// timestamp as int
+			array('February 13, 2009 at 11:31:30 PM GMT+0', 'en', 'datetime', 1234567890),
+			array('13. Februar 2009 um 23:31:30 GMT+0', 'de', 'datetime', 1234567890),
+			array('February 13, 2009', 'en', 'date', 1234567890),
+			array('13. Februar 2009', 'de', 'date', 1234567890),
+			array('11:31:30 PM GMT+0', 'en', 'time', 1234567890),
+			array('23:31:30 GMT+0', 'de', 'time', 1234567890),
+
+			// DateTime object
+			array('February 13, 2009 at 11:31:30 PM GMT+0', 'en', 'datetime', new DateTime('@1234567890')),
+			array('13. Februar 2009 um 23:31:30 GMT+0', 'de', 'datetime', new DateTime('@1234567890')),
+			array('February 13, 2009', 'en', 'date', new DateTime('@1234567890')),
+			array('13. Februar 2009', 'de', 'date', new DateTime('@1234567890')),
+			array('11:31:30 PM GMT+0', 'en', 'time', new DateTime('@1234567890')),
+			array('23:31:30 GMT+0', 'de', 'time', new DateTime('@1234567890')),
+
+			// en_GB
+			array('13 February 2009 at 23:31:30 GMT+0', 'en_GB', 'datetime', new DateTime('@1234567890')),
+			array('13 February 2009', 'en_GB', 'date', new DateTime('@1234567890')),
+			array('23:31:30 GMT+0', 'en_GB', 'time', new DateTime('@1234567890')),
+			array('13 February 2009 at 23:31:30 GMT+0', 'en-GB', 'datetime', new DateTime('@1234567890')),
+			array('13 February 2009', 'en-GB', 'date', new DateTime('@1234567890')),
+			array('23:31:30 GMT+0', 'en-GB', 'time', new DateTime('@1234567890')),
+		);
+	}
+
 	/**
-	 * Issue #4360: Do not call strtotime() on numeric strings.
+	 * @dataProvider localizationDataProvider
 	 */
-	public function testNumericStringToDateTime() {
+	public function testNumericStringLocalization($expectedDate, $lang, $type, $value) {
 		$l = new OC_L10N('test');
-		$this->assertSame('February 13, 2009 23:31', $l->l('datetime', '1234567890'));
+		$l->forceLanguage($lang);
+		$this->assertSame($expectedDate, $l->l($type, $value));
+	}
+
+	public function firstDayDataProvider() {
+		return array(
+			array(1, 'de'),
+			array(0, 'en'),
+		);
 	}
 
-	public function testNumericToDateTime() {
+	/**
+	 * @dataProvider firstDayDataProvider
+	 * @param $expected
+	 * @param $lang
+	 */
+	public function testFirstWeekDay($expected, $lang) {
 		$l = new OC_L10N('test');
-		$this->assertSame('February 13, 2009 23:31', $l->l('datetime', 1234567890));
+		$l->forceLanguage($lang);
+		$this->assertSame($expected, $l->l('firstday', 'firstday'));
 	}
 
 	/**
diff --git a/tests/lib/util.php b/tests/lib/util.php
index 600b794d8b8137c7ad23fad156483827a17e2f4a..9a3185b3f792926909845143e830a2f95db262b0 100644
--- a/tests/lib/util.php
+++ b/tests/lib/util.php
@@ -29,7 +29,7 @@ class Test_Util extends PHPUnit_Framework_TestCase {
 		date_default_timezone_set("UTC");
 
 		$result = OC_Util::formatDate(1350129205);
-		$expected = 'October 13, 2012 11:53';
+		$expected = 'October 13, 2012 at 11:53:25 AM GMT+0';
 		$this->assertEquals($expected, $result);
 
 		$result = OC_Util::formatDate(1102831200, true);
@@ -41,7 +41,7 @@ class Test_Util extends PHPUnit_Framework_TestCase {
 		date_default_timezone_set("UTC");
 
 		$result = OC_Util::formatDate(1350129205, false, 'Europe/Berlin');
-		$expected = 'October 13, 2012 13:53';
+		$expected = 'October 13, 2012 at 1:53:25 PM GMT+0';
 		$this->assertEquals($expected, $result);
 	}
 
@@ -57,7 +57,7 @@ class Test_Util extends PHPUnit_Framework_TestCase {
 
 		\OC::$server->getSession()->set('timezone', 3);
 		$result = OC_Util::formatDate(1350129205, false);
-		$expected = 'October 13, 2012 14:53';
+		$expected = 'October 13, 2012 at 2:53:25 PM GMT+0';
 		$this->assertEquals($expected, $result);
 	}