I'm not sure why it is modifying the data like that when displaying, but you can use
$post->post_date_gmt
This will return the scheduled post date the same as it is in the DB except it's in GMT time format, so you might need to convert the time to your local time zone first (this blog post may help). Otherwise, you should be able to use it as is if you're just using the date & not the time but it depends on what you're doing with it.
Edit 2/29/12:
I wanted to elaborate on my answer to make it more complete and give you something you can actually use.
You're right, the post date is being stored in the post_date field in the database.
For example, wordpress uses this line of code in wp-admin/includes/meta-boxes.php to set the variable that is used to display the post's date for drafts scheduled for the future:
$date = date_i18n( $datef, strtotime( $post->post_date ) );
However, when using the same code for display on the front end, it returns the current time like you said. I think we can conclude that the $post object data is being prepared differently for the front end.
Anyways, it is possible to output the same scheduled date that you have set in the admin.
Because it seems like we can't use $post->post_date, we can use $post->post_date_gmt like I said before - the only downside is that your timezone probably isn't the same as GMT. So all you need to do is pull the GMT value and convert it to your timezone.
You can add this function to your functions.php and call it wherever you want:
<?php
/**
*@param string $datef (optional) to pass the format you want for the returned date string
*@return string
*/
function get_the_real_post_date($datef = 'M j, Y @ G:i') {
global $post;
if ( !empty( $timezone_string = get_option( 'timezone_string' ) ) ) {
$timezone_object = timezone_open( $timezone_string );
$datetime_object = date_create( $post->post_date_gmt );
$offset_sec = round( timezone_offset_get( $timezone_object, $datetime_object ) );
// if you want $offset_hrs = round( $offset_sec / 3600 );
return date_i18n( $datef, strtotime( $post->post_date_gmt ) + $offset_sec );
} elseif (!empty( $offset_hrs = get_option('gmt_offset') ) ) {
// this option shows empty for me so I believe it's only used by WP pre 3.0
// the option stores an integer value for the time offset in hours
$offset_sec = $offset_hrs * 3600;
return date_i18n( $datef, strtotime( $post->post_date_gmt ) + $offset_sec );
} else {
return; // shouldn't happen but...
}
}
Of course you could also change the default time format that is defined in the parameter definition if there is a particular format you would use the most.
Let me know if this works for you. I'm curious, what are you using the date for?