Forum Moderators: coopster

Message Too Old, No Replies

My bone headed blunder! Date Conversion Question

         

Shaman13

10:25 pm on Dec 13, 2004 (gmt 0)

10+ Year Member



Well here I am back for another installment of HELP! When I created my database I inadvertently made one of my date fields into a varchar data type. Now I can't figure out how to change the field to date type without losing my data! Can it be done? If so how? Any and All suggestions are welcome! Thanks in Advance!

dreamcatcher

1:33 am on Dec 14, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You should be able to edit your field type in your SQL admin program. If not, why not just take a backup of your database, re-create the table, then re-upload the information? You`ll may also need to change your data slightly, but shouldn`t take too long.

coopster

2:50 am on Dec 14, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



If the column is already in the date format (yyyy-mm-dd) then you could simply use the ALTER TABLE syntax to update your column...
ALTER TABLE table MODIFY mydatecolumn DATE;
However, as dreamcatcher recommended, and I concur, always, always backup your file prior to mass modifications so you have something to fall back on in case things don't work out as planned.

Salsa

3:10 am on Dec 14, 2004 (gmt 0)

10+ Year Member



I agree with dreamcatcher and coopster to backup before doing anything. If the data is in a format like yyyy-mm-dd, as Coopster suggested, you've got it made. If it isn't so consistent, however, I'd ADD a DATE column called something like same_name_as_origninal_2, and construct however many queries as are necessary to convert the old data to fully populate the new column based on the values in the old column. Once that is done, drop the old column and rename the new column to the old name.

Shaman13

3:52 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Thanks coopster,dreamcatcher and Salsa. Excellent suggestions and information from you all! I will give it a try and let you know how I make out.

Shaman13

6:41 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Well I guess I have got my work cut out for me! Unfortunately the column is NOT in 0000/00/00 format. I have decided to use Salsa's idea of adding a column and updating it with queries. I must admit I haven't the foggiest of where to begin. Does anyone have an example of a query I can start with? Thanks for all the guidance so far. Have a Great Day!

bfillmer

7:53 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



You could probably create a temp page and run the following:


$sql = "select date_column_name from table_name";
$qryrslt = mysql_query($sql);
while( $row = mysql_fetch_array($qryrslt,MYSQL_ASSOC) ) {
$tmpdate = $row["date_column_name"];
// Perform whatever conversion you need here on the
// $tmpdate variable.
$sql = "insert into table_name (new_date_column_name) values ($tmpdate);"
mysql_query($sql);
}

This assumes you have a connection to the db established.

Back up the database first.

Salsa

8:58 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



The first step will be to exhaust the examples of how the dates are currently formatted. The only case I can forsee that might cause problems is if you were to have both 12/14/2004 and 14/12/2004 type formats. In those cases you could easily see that 14/12/2004 is the European format, and reformat it accordingly. But the likes of 12/12/2004 would create an unresolveable problem--if both formats have been used in the column.

For a do-able example, like a "December 14, 2004" type format, In your while loop through all the $row['old_date'] results, use a regex to catch anything starting with a spelled out month (or abreviation), followed by a comma or space or both, followed by one or two numbers (day of month), followed by a comma or space or both, and ending with a two to four didgets (year). Later, strtotime() [us2.php.net] should accept about anything the regex does, except for a misspelled month name or abreviation:

if (preg_match('!^([^\d, ]+[, ]{1,2}\d{1,2}[, ]{1,2}\d{2,4}$!i'),$row['old_date']){ 
echo $row['old_date']." is a match.<br>\n";
if (!$new_date = date('Y-m-d',strtotime($row['old_date']))) {
echo "The month must be misspelled<br>\n";
}
else echo "\$new_date = $new_date<br>\n";
}
else {
echo $row['old_date']." is not a match.<br>\n";
/* Add as many elseifs and regexs for different old_date formats.
Most other formats, I'm thinking you can explode on a / or the like
and concatenate the rearranged elements to get ccyy-mm-dd */
}

I'm getting better at this stuff, because I tested this, and I actually got my regex right the first time! (I don't think that's ever happened before. :)

Shaman13

9:18 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Salsa Thanks for the response! Fortunately my dates are all in the mm/dd/yyyy format in the varchar column. I have scanned all the data and this is the only format present. Does this simplify things? How do I run the code you gave me? No I am not dumb as a stone. But I am so new to this Php stuff I am only taking baby steps. Again your suggestions and time are greatly appreciated!

Salsa

9:24 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Absolutely easier!

$date_elements = explode('/',$row['old_date']); 
$new_date = $date_elements[2]."-".$date_elements[0]."-".$date_elements[1];

jollymcfats

9:59 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



or, if you're using MySQL:

ALTER TABLE table ADD COLUMN newdate DATE;

UPDATE table SET newdate=CONCAT_WS('-', SUBSTRING(olddate,7,4), SUBSTRING(olddate,1,2), SUBSTRING(olddate,4,2));

(which is essentially the same as the above PHP, just done entirely in the database.)

if you're satisified with the contents of newdate, you can drop olddate and rename newdate to olddate.

Salsa

10:21 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Cool, jollymcfats. Your solution is even faster and cleaner.

bfillmer

10:25 pm on Dec 14, 2004 (gmt 0)

10+ Year Member



Definitely cleaner and faster.

coopster

12:55 am on Dec 15, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



<added>
Right on, jollymcfats. I was getting ready to post this earlier, but got distracted; solution examples were posted in the meantime, but since I had it keyed up I figured I'd drop the snippet anyway --
coopster
</added>

I would write a quick script to validate the data in your file to make sure they are all valid dates in that format.

<pre> 
<?php
$sql = "SELECT mydate FROM mytable";
// execute your database query
while ($row = fetch from the result set) {
$month = substr [php.net]($row['mydate'], 0, 2);
$day = substr($row['mydate'], 3, 2);
$year = substr($row['mydate'], 6, 4);
if (!checkdate [php.net]($month, $day, $year)) {
print "Bad one: " . $row['mydate'] . "\n";
}
}
?>
</pre>

Then, if it all looks good, I would run a couple of database queries as suggested to ADD the new column, UPDATE it with information from the incorrectly formatted column, DROP the original column and RENAME the new column to the original column name.
-- 
-- ADD the new column:
--
ALTER TABLE table ADD mynewdate DATE AFTER mydate;
--
-- Here is where you can get fancy, depending on your database.
-- I'll use MySQL examples:
--
-- MySQL >= 4.1.1
--
UPDATE table SET mynewdate = STR_TO_DATE(mydate, '%m/%d/%Y');
--
-- MySQL < 4.1.1
--
UPDATE table
SET mynewdate = CONCAT_WS('-',
SUBSTRING(mydate, 7, 4),
SUBSTRING(mydate, 1, 2),
SUBSTRING(mydate, 4, 2))
;
--
-- Drop the original column:
--
ALTER TABLE table DROP mydate;
--
-- Rename the new column of new type DATE to the original name:
--
ALTER TABLE table CHANGE mynewdate mydate DATE;

Shaman13

3:29 pm on Dec 15, 2004 (gmt 0)

10+ Year Member



Wow! Thanks for all the great suggestions guys! I have some questions though cause I am new to this stuff! Coopster How do I run you script to check the integrity of the data? I created a page with the script on it but it doesn't seem to run. I know this probably qualifies as the stupidest question of the day. But could you tell me how to run this ....

<pre>
<?php $sql = "SELECT DOPEN FROM _clientsw_copy";
// execute your database query
while ($row = fetch from the result set) { $month = substr($row['DOPEN'], 0, 2);

$day = substr($row['DOPEN'], 3, 2); $year = substr($row['DOPEN'], 6, 4);
if (!checkdate($month, $day, $year)) { print "Bad one: " . $row['DOPEN'] . "\n"; } }?>
</pre>

Thanks to all of you who responded to my post! This is one of the best forums I have participated in! All of you! Have an Awesome Day!

coopster

6:56 pm on Dec 15, 2004 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



There are no stupid questions on this forum, message #7 [webmasterworld.com] ;)


// execute your database query
while ($row = fetch from the result set)

These were just comments because I did not know which database you were using. You need to replace them with the actual functions corresponding to the database. For example, if it was MySQL you need to first connect to your database, then execute the script.


<pre>
<?php
$connection = mysql_connect('localhost', 'username', 'password')
or exit('Could not connect (' . mysql_errno() . '): ' . mysql_error());
$db = mysql_select_db('databasename', $connection)
or exit('Could not select database (' . mysql_errno() . '): ' . mysql_error());
$sql = "SELECT DOPEN FROM _clientsw_copy";
// execute your database query
$rows = mysql_query [php.net]($sql);
while ($row = mysql_fetch_array [php.net]($rows)) {
$month = substr($row['DOPEN'], 0, 2);
$day = substr($row['DOPEN'], 3, 2);
$year = substr($row['DOPEN'], 6, 4);
if (!checkdate($month, $day, $year)) {
print "Bad one: " . $row['DOPEN'] . "\n";
}
}
?>
</pre>

Shaman13

8:24 pm on Dec 16, 2004 (gmt 0)

10+ Year Member



Thanks for the clarification Coopster! I will give it a try. Have an Awesome Day!