diff --git src/wp-includes/functions.php src/wp-includes/functions.php
index 292abf9..e594327 100644
--- src/wp-includes/functions.php
+++ src/wp-includes/functions.php
@@ -91,13 +91,7 @@ function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
 	$i = $unixtimestamp;
 
 	if ( false === $i ) {
-		if ( ! $gmt )
-			$i = current_time( 'timestamp' );
-		else
-			$i = time();
-		// we should not let date() interfere with our
-		// specially computed timestamp
-		$gmt = true;
+		$i = current_time( 'timestamp', $gmt );
 	}
 
 	/*
@@ -106,15 +100,13 @@ function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
 	 */
 	$req_format = $dateformatstring;
 
-	$datefunc = $gmt? 'gmdate' : 'date';
-
 	if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
-		$datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
+		$datemonth = $wp_locale->get_month( date( 'm', $i ) );
 		$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
-		$dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
+		$dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
 		$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
-		$datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
-		$datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
+		$datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) );
+		$datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) );
 		$dateformatstring = ' '.$dateformatstring;
 		$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
 		$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
@@ -142,7 +134,7 @@ function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
 			}
 		}
 	}
-	$j = @$datefunc( $dateformatstring, $i );
+	$j = @date( $dateformatstring, $i );
 
 	/**
 	 * Filters the date formatted based on the locale.
@@ -563,7 +555,7 @@ function do_enclose( $content, $post_ID ) {
 	global $wpdb;
 
 	//TODO: Tidy this ghetto code up and make the debug code optional
-	include_once( ABSPATH . WPINC . '/class-IXR.php' ); 
+	include_once( ABSPATH . WPINC . '/class-IXR.php' );
 
 	$post_links = array();
 
diff --git tests/phpunit/tests/date/dateI18n.php tests/phpunit/tests/date/dateI18n.php
new file mode 100644
index 0000000..108bd94
--- /dev/null
+++ tests/phpunit/tests/date/dateI18n.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @group date
+ * @group datetime
+ */
+class Tests_Date_I18n extends WP_UnitTestCase {
+	public function test_should_format_date() {
+		$expected = date( 'Y-m-d H:i:s' );
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s' ) );
+	}
+
+	public function test_should_use_custom_timestamp() {
+		$expected = '2012-12-01 00:00:00';
+
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', strtotime( '2012-12-01 00:00:00' ) ) );
+	}
+
+	public function test_date_should_be_in_gmt() {
+		$expected = date( 'Y-m-d H:i:s' );
+
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', false, true ) );
+	}
+
+	public function test_custom_timestamp_ignores_gmt_setting() {
+		$expected = '2012-12-01 00:00:00';
+
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', strtotime( '2012-12-01 00:00:00' ), false ) );
+	}
+
+	public function test_custom_timezone_setting() {
+		update_option( 'timezone_string', 'Europe/London' );
+		$expected = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d H:i:s' ) ) + HOUR_IN_SECONDS );
+
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s' ) );
+	}
+
+	public function test_date_should_be_in_gmt_with_custom_timezone_setting() {
+		update_option( 'timezone_string', 'Europe/London' );
+		$expected = date( 'Y-m-d H:i:s' );
+
+		$this->assertNotEquals( date_i18n( 'Y-m-d H:i:s', false, false ), date_i18n( 'Y-m-d H:i:s', false, true ) );
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', false, true ) );
+	}
+
+	public function test_date_should_be_in_gmt_with_custom_timezone_setting_and_timestamp() {
+		update_option( 'timezone_string', 'Europe/London' );
+
+		$expected = '2012-12-01 00:00:00';
+
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', strtotime( '2012-12-01 00:00:00' ), false ) );
+		$this->assertEquals( $expected, date_i18n( 'Y-m-d H:i:s', strtotime( '2012-12-01 00:00:00' ), true ) );
+	}
+
+	public function test_adjusts_format_based_on_locale() {
+		$locale = clone $GLOBALS['wp_locale'];
+
+		// Change $GLOBALS['wp_locale']
+
+		$GLOBALS['wp_locale'] = $locale;
+
+		$this->markTestIncomplete( 'Work in progress' );
+	}
+}
