Index: src/wp-includes/class-wp-xmlrpc-server.php
===================================================================
--- src/wp-includes/class-wp-xmlrpc-server.php	(revision 36121)
+++ src/wp-includes/class-wp-xmlrpc-server.php	(working copy)
@@ -3427,7 +3427,7 @@
 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force
 			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
 			$comment_date = iso8601_to_datetime( $dateCreated );
-			$comment_date_gmt = get_gmt_from_date( $comment_date );
+			$comment_date_gmt = iso8601_to_datetime( $dateCreated, 'gmt' );
 		}
 
 		if ( isset($content_struct['content']) )
@@ -4998,14 +4998,15 @@
 		}
 
 		// Do some timestamp voodoo
-		if ( !empty( $content_struct['date_created_gmt'] ) )
+		if ( !empty( $content_struct['date_created_gmt'] ) ) {
 			// We know this is supposed to be GMT, so we're going to slap that Z on there by force
-			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
-		elseif ( !empty( $content_struct['dateCreated']) )
-			$dateCreated = $content_struct['dateCreated']->getIso();
+			$dateCreated = iso8601_to_datetime( rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z' );
+		} elseif ( !empty( $content_struct['dateCreated']) ) {
+			$dateCreated = iso8601_to_datetime( $content_struct['dateCreated']->getIso() );
+		}
 
 		if ( !empty( $dateCreated ) ) {
-			$post_date = iso8601_to_datetime( $dateCreated );
+			$post_date = $dateCreated;
 			$post_date_gmt = get_gmt_from_date( $post_date );
 		} else {
 			$post_date = '';
@@ -5355,16 +5356,17 @@
 				$to_ping = implode(' ', $to_ping);
 		}
 
-		// Do some timestamp voodoo.
-		if ( !empty( $content_struct['date_created_gmt'] ) )
-			// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
-			$dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
-		elseif ( !empty( $content_struct['dateCreated']) )
-			$dateCreated = $content_struct['dateCreated']->getIso();
+		// Do some timestamp voodoo
+		if ( !empty( $content_struct['date_created_gmt'] ) ) {
+			// We know this is supposed to be GMT, so we're going to slap that Z on there by force
+			$dateCreated = iso8601_to_datetime( rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z' );
+		} elseif ( !empty( $content_struct['dateCreated']) ) {
+			$dateCreated = iso8601_to_datetime( $content_struct['dateCreated']->getIso() );
+		}
 
 		if ( !empty( $dateCreated ) ) {
-			$post_date = iso8601_to_datetime( $dateCreated );
-			$post_date_gmt = get_gmt_from_date( $post_date, 'GMT' );
+			$post_date = $dateCreated;
+			$post_date_gmt = get_gmt_from_date( $post_date );
 		} else {
 			$post_date     = $postdata['post_date'];
 			$post_date_gmt = $postdata['post_date_gmt'];
Index: src/wp-includes/formatting.php
===================================================================
--- src/wp-includes/formatting.php	(revision 36121)
+++ src/wp-includes/formatting.php	(working copy)
@@ -2673,26 +2673,33 @@
  * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s.
  */
 function iso8601_to_datetime( $date_string, $timezone = 'user' ) {
-	$timezone = strtolower($timezone);
+	$timezone = strtolower( $timezone );
 
-	if ($timezone == 'gmt') {
+	$tzstring = get_option( 'timezone_string' );
 
-		preg_match('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', $date_string, $date_bits);
+	if ( empty( $tzstring ) ) {
+		$tzstring = date_default_timezone_get();
+	}
 
-		if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset
-			$offset = iso8601_timezone_to_offset($date_bits[7]);
-		} else { // we don't have a timezone, so we assume user local timezone (not server's!)
-			$offset = HOUR_IN_SECONDS * get_option('gmt_offset');
-		}
+	$tz = timezone_open( $tzstring );
 
-		$timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]);
-		$timestamp -= $offset;
+	if ( false === $tz ) {
+		return '0000-00-00 00:00:00';
+	}
 
-		return gmdate('Y-m-d H:i:s', $timestamp);
+	$datetime = date_create( $date_string, $tz );
 
-	} elseif ($timezone == 'user') {
-		return preg_replace('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', '$1-$2-$3 $4:$5:$6', $date_string);
+	if ( false === $datetime ) {
+		return '0000-00-00 00:00:00';
 	}
+
+	if ( 'gmt' === $timezone ) {
+		date_timezone_set( $datetime, timezone_open( 'UTC' ) );
+	} else {
+		date_timezone_set( $datetime, $tz );
+	}
+
+	return date_format( $datetime, 'Y-m-d H:i:s' );
 }
 
 /**
Index: tests/phpunit/tests/formatting/DateTime.php
===================================================================
--- tests/phpunit/tests/formatting/DateTime.php	(revision 0)
+++ tests/phpunit/tests/formatting/DateTime.php	(working copy)
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * @group formatting
+ */
+class Tests_Formatting_DateTime extends WP_UnitTestCase {
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_bad_timezone_strings() {
+		$tz = get_option( 'timezone_string' );
+
+		try {
+
+			update_option( 'timezone_string', '' );
+			$this->assertEquals( '1984-01-11 05:00:00', iso8601_to_datetime( '1984-01-11T05:00:00', 'gmt' ) );
+
+			update_option( 'timezone_string', 'garbage' ); // will get set to empty string
+			$this->assertEquals( '1984-01-11 05:00:00', iso8601_to_datetime( '1984-01-11T05:00:00', 'gmt' ) );
+
+		} catch ( Exception $e ) {}
+
+		update_option( 'timezone_string', $tz );
+
+		// no 'finally' until PHP 5.5+ 
+		if ( isset( $e ) ) {
+			throw $e;
+		}
+	}
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_invalid_dates() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'UTC' );
+
+		try {
+
+			$this->assertEquals( '-0001-11-30 00:00:00', iso8601_to_datetime( '0000-00-00T00:00:00Z' ), 'all zeroes' );
+			$this->assertEquals( '0000-00-00 00:00:00', iso8601_to_datetime( '1984-01-11T05:00:00+XYZ' ), 'invalid TZ' );
+
+		} catch ( Exception $e ) {}
+
+		update_option( 'timezone_string', $tz );
+
+		// no 'finally' until PHP 5.5+ 
+		if ( isset( $e ) ) {
+			throw $e;
+		}
+	}
+
+	function test_utc() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'UTC' );
+
+		$date_string = '1984-01-11 05:00:00';
+
+		try {
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00Z', 'gmt' ), 'Z, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00-0200', 'gmt' ), '-0200, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T04:00:00-0100', 'gmt' ), '-0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00+0000', 'gmt' ), '+0000, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T06:00:00+0100', 'gmt' ), '+0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T07:00:00+0200', 'gmt' ), '+0200, gmt' );
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00Z', 'user' ), 'Z, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00-0200', 'user' ), '-0200, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T04:00:00-0100', 'user' ), '-0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00+0000', 'user' ), '+0000, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T06:00:00+0100', 'user' ), '+0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T07:00:00+0200', 'user' ), '+0200, user' );
+		
+		} catch ( Exception $e ) {}
+
+		update_option( 'timezone_string', $tz );
+
+		// no 'finally' until PHP 5.5+ 
+		if ( isset( $e ) ) {
+			throw $e;
+		}
+	}
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_america_newyork() {
+		// America/New_York is UTC-05:00 (UTC-04:00 DST)
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'America/New_York' );
+
+		$date_string = '1984-01-11 05:00:00';
+
+		try {
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00Z', 'gmt' ), 'Z, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00-0200', 'gmt' ), '-0200, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T04:00:00-0100', 'gmt' ), '-0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00+0000', 'gmt' ), '+0000, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T06:00:00+0100', 'gmt' ), '+0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T07:00:00+0200', 'gmt' ), '+0200, gmt' );
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T10:00:00Z', 'user' ), 'Z, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T08:00:00-0200', 'user' ), '-0200, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T09:00:00-0100', 'user' ), '-0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T10:00:00+0000', 'user' ), '+0000, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T11:00:00+0100', 'user' ), '+0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T12:00:00+0200', 'user' ), '+0200, user' );
+
+		} catch ( Exception $e ) {}
+
+		update_option( 'timezone_string', $tz );
+
+		// no 'finally' until PHP 5.5+ 
+		if ( isset( $e ) ) {
+			throw $e;
+		}
+	}
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_africa_johannesburg() {
+		// Africa/Johannesburg is UTC+02:00
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'Africa/Johannesburg' );
+
+		$date_string = '1984-01-11 05:00:00';
+
+		try {
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00Z', 'gmt' ), 'Z, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00-0200', 'gmt' ), '-0200, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T04:00:00-0100', 'gmt' ), '-0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00+0000', 'gmt' ), '+0000, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T06:00:00+0100', 'gmt' ), '+0100, gmt' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T07:00:00+0200', 'gmt' ), '+0200, gmt' );
+
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00Z', 'user' ), 'Z, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T01:00:00-0200', 'user' ), '-0200, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T02:00:00-0100', 'user' ), '-0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T03:00:00+0000', 'user' ), '+0000, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T04:00:00+0100', 'user' ), '+0100, user' );
+			$this->assertEquals( $date_string, iso8601_to_datetime( '19840111T05:00:00+0200', 'user' ), '+0200, user' );
+
+		} catch ( Exception $e ) {}
+
+		update_option( 'timezone_string', $tz );
+
+		// no 'finally' until PHP 5.5+ 
+		if ( isset( $e ) ) {
+			throw $e;
+		}
+	}
+
+}

Property changes on: tests/phpunit/tests/formatting/DateTime.php
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: tests/phpunit/tests/xmlrpc/mw/editPost.php
===================================================================
--- tests/phpunit/tests/xmlrpc/mw/editPost.php	(revision 36121)
+++ tests/phpunit/tests/xmlrpc/mw/editPost.php	(working copy)
@@ -246,6 +246,64 @@
 	}
 
 	/**
+	 * @ticket 35053
+	 */
+	function test_post_date_dateCreated_gmt_timezone_conversion() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'America/New_York' );
+
+		$editor_id = $this->make_user_by_role( 'editor' );
+
+		$post_id = self::factory()->post->create( array(
+			'post_author' => $editor_id
+		) );
+
+		$date_string = '1984-01-11 05:00:00';
+		// America/New_York's time zone is -5:00 so add 5 hours
+		$date_string_gmt = '1984-01-11 10:00:00';
+
+		$result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'editor', 'editor', array(
+			'dateCreated' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string_gmt, false ) . 'Z' ),
+		) ) );
+
+		$fetched_post = get_post( $post_id );
+
+		update_option( 'timezone_string', $tz );
+
+		$this->assertTrue( $result );
+		$this->assertEquals( $date_string, $fetched_post->post_date );
+	}
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_post_date_gmt_timezone_conversion() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'America/New_York' );
+
+		$editor_id = $this->make_user_by_role( 'editor' );
+
+		$post_id = self::factory()->post->create( array(
+			'post_author' => $editor_id
+		) );
+
+		$date_string = '1984-01-11 05:00:00';
+		// America/New_York's time zone is -5:00 so add 5 hours
+		$date_string_gmt = '1984-01-11 10:00:00';
+
+		$result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'editor', 'editor', array(
+			'date_created_gmt' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string_gmt, false ) ),
+		) ) );
+
+		$fetched_post = get_post( $post_id );
+
+		update_option( 'timezone_string', $tz );
+
+		$this->assertTrue( $result );
+		$this->assertEquals( $date_string, $fetched_post->post_date );
+	}
+
+	/**
 	 * @ticket 16980
 	 */
 	function test_empty_not_null() {
Index: tests/phpunit/tests/xmlrpc/mw/newPost.php
===================================================================
--- tests/phpunit/tests/xmlrpc/mw/newPost.php	(revision 36121)
+++ tests/phpunit/tests/xmlrpc/mw/newPost.php	(working copy)
@@ -193,4 +193,55 @@
 		$this->assertStringMatchesFormat( '%d', $result );
 		$this->assertEquals( $date_string , $fetched_post->post_date );
 	}
+
+	/**
+	 * @ticket 35053
+	 */
+	function test_post_date_dateCreated_gmt_timezone_conversion() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'America/New_York' );
+
+		$this->make_user_by_role( 'editor' );
+		$date_string = '1984-01-11 05:00:00';
+		// America/New_York's time zone is -5:00 so add 5 hours
+		$date_string_gmt = '1984-01-11 10:00:00';
+		$post = array(
+			'title' => 'test',
+			'post_content' => 'test',
+			'dateCreated' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string_gmt, false ) . 'Z' )
+		);
+		$result = $this->myxmlrpcserver->mw_newPost( array( 1, 'editor', 'editor', $post ) );
+		$fetched_post = get_post( $result );
+
+		update_option( 'timezone_string', $tz );
+
+		$this->assertStringMatchesFormat( '%d', $result );
+		$this->assertEquals( $date_string , $fetched_post->post_date );
+	}
+	
+	/**
+	 * @ticket 35053
+	 */
+	function test_post_date_gmt_timezone_conversion() {
+		$tz = get_option( 'timezone_string' );
+		update_option( 'timezone_string', 'America/New_York' );
+
+		$this->make_user_by_role( 'editor' );
+		$date_string = '1984-01-11 05:00:00';
+		// America/New_York's time zone is -5:00 so add 5 hours
+		$date_string_gmt = '1984-01-11 10:00:00';
+		$post = array(
+			'title' => 'test',
+			'post_content' => 'test',
+			'date_created_gmt' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string_gmt, false ) )
+		);
+		$result = $this->myxmlrpcserver->mw_newPost( array( 1, 'editor', 'editor', $post ) );
+		$fetched_post = get_post( $result );
+
+		update_option( 'timezone_string', $tz );
+
+		$this->assertStringMatchesFormat( '%d', $result );
+		$this->assertEquals( $date_string , $fetched_post->post_date );
+	}
+
 }
Index: tests/phpunit/tests/xmlrpc/wp/editComment.php
===================================================================
--- tests/phpunit/tests/xmlrpc/wp/editComment.php	(revision 36121)
+++ tests/phpunit/tests/xmlrpc/wp/editComment.php	(working copy)
@@ -91,8 +91,10 @@
 		$comment_id = wp_insert_comment( $comment_data );
 
 		$date_string = '1984-01-11 05:00:00';
+		// America/New_York's time zone is -5:00 so add 5 hours
+		$date_string_gmt = '1984-01-11 10:00:00';
 		$result = $this->myxmlrpcserver->wp_editComment( array( 1, 'administrator', 'administrator', $comment_id, array(
-			'date_created_gmt' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string, false ) )
+			'date_created_gmt' => new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date_string_gmt, false ) )
 		) ) );
 		$fetched_comment = get_comment( $comment_id );
 
@@ -101,4 +103,4 @@
 		$this->assertTrue( $result );
 		$this->assertEquals( $date_string, $fetched_comment->comment_date );
 	}
-}
\ No newline at end of file
+}
