MySQL


For formatting dates in MySQL one can use the DATE_FORMAT function like DATE_FORMAT(`date_col or value`, dateFormatString)

In a select query, that looks like SELECT DATE_FORMAT(`date_col or value`, dateFormatString) FROM `tableName`
. In case one wants to use the server current date, the query would look like SELECT DATE_FORMAT(NOW(), dateFormatString) FROM `tableName`

For a detailed explanation of the options that can be in a dateFormatString, read the MySQL date related page (dev.mysql.com/doc/).

In the general examples below, I will use the date 22 April 2007 16:15:23 (date of creation of this article)

Language Format String Output
English %m/%d/%Y 04/22/2007
English %m/%d/%Y %H:%i 04/22/2007 16:15
English %a, %D %b %Y %H:%i Sun, 22nd Apr 2007 16:15
Français %d-%m-%Y 22-04-2007
Français %d-%m-%Y %H:%i 22-04-2007 16:15
Français %a, %D %b %Y %H:%i Dim, 22 Avr 2007 16:15
Ikinyarwanda %d-%m-%Y 22-04-2007
Ikinyarwanda %d-%m-%Y %H:%i 22-04-2007 16:15
Ikinyarwanda %a, %D %b %Y %H:%i Cyu, 22 Mata 2007 16:15
Svenska %Y-%m-%d 2007-04-22
Svenska %Y-%m-%d %H:%i 2007-04-22 16:15
Svenska %Y-%m-%d %H:%i 22-april-2007 16:15

For PHP formatString, visit http://www.php.net/date

In some installations of the MySQL server, some invalid dates are legal.

At the URL http://dev.mysql.com/doc/refman/4.1/en/date-and-time-types.html I can read:
MySQL version through 4.1 accept certain “illegal” values for dates, such as '1999-11-31'. This is useful when you want to store a possibly incorrect value specified by a user (for example, in a web form) in the database for future processing. MySQL verifies only that the month is in the range from 0 to 12 and that the day is in the range from 0 to 31. These ranges are defined to include zero because MySQL allows you to store dates where the day or month and day are zero in a DATE or DATETIME column. This is extremely useful for applications that need to store a birthdate for which you do not know the exact date. In this case, you simply store the date as '1999-00-00' or '1999-01-00'. If you store dates such as these, you should not expect to get correct results for functions such as DATE_SUB() or DATE_ADD that require complete dates.

MySQL also allows you to store '0000-00-00' as a “dummy date.” This is in some cases more convenient, and uses less data and index space, than storing NULL values.

This behaviour causes problems when using the MySQL Connector/NET. First, Visual Studio 2005 DateTime structure does not accept such invalid date values. It only accepts values between “0001-01-01 00:00:00″ through “9999-12-31 23:59:59.99999″ and these values should be real dates (Check remarks at system.datetime ).

To deal with this problem, connector/NET has MySqlDateTime type that can contain such invalid dates. This class has a property, IsValidDateTime, that is set to true when the date is valid and false otherwise. Currently, the way this property is calculated does not guarantee that the value contained in a MySqlDateTime object can be easily converted into a legal DateTime object. Currently, this property will return FALSE if and only if the object contains a ZERO date (or ZERO dateTime: 0000-00-00).

To overcome this, the property checking should also check if this date is legal in .NET
I have created a sample function that can replace the one in Connector/Net 1.0.7 and I named it IsStrictlyValidDateTime.

Its definition looks like:

[code lang="C#"]
///
/// Indicates if this object contains a value that can be represented as a DateTime
///
public bool IsStrictlyValidDateTime
{
get
{
// In case this represents a zero date, return FALSE
if (year == 0 || month == 0 || day == 0)
{
return false;
}

// Check http://msdn2.microsoft.com/en-us/library/xcfzdy4x(d=ide).aspx
// Here I try assign the value of this object to a DateTime object.
// In case the date is illegal, an Exception will be thrown
// In case the date is legal, the value will be accepted
try
{
DateTime dt = new DateTime(year, month, day);
return true;
} catch (ArgumentOutOfRangeException)
{
//year is less than 1 or greater than 9999.
//-or-
//month is less than 1 or greater than 12.
//-or-
//day is less than 1 or greater than the number of days in month
return false;
} catch (ArgumentException)
{
// The specified parameters evaluate to less than MinValue or more than MaxValue
return false;
}
}
}
[/code]

And the changed file can be seen at /Types/MySqlDateTime.cs

I still don’t understand why a date like “0000-10-01″ was made invalid in .NET (ten months after date ZERO).

In MySql connector .NET, the MySqlDateTime class has no public constructor (it does have constructors but defined as internal). This makes it impossible to use that type in applications.

The bug at MySQL Bug #15112 is caused by the absent public contructor. To try and solve this problem, I added a public contructor in the file mysql-connector-net-1.0.7\mysqlclient\Types\MySqlDateTime.cs
[code lang="C#"]public MySqlDateTime()
{
// Set the value to the lowest value that a DateTime value can have
year = 1;
month = 1;
day = 1;
}
public MySqlDateTime(DateTime val)
{
year = val.Year;
month = val.Month;
day = val.Day;
hour = val.Hour;
minute = val.Minute;
second = val.Second;
}[/code]

This makes it possible to instantiate a MySqlDateTime and set it values.
One can do like :
[code lang="C#"] MySql.Data.Types.MySqlDateTime myDate = new MySql.Data.Types.MySqlDateTime();
System.Console.WriteLine(myDate.ToString()); // 0001-01-01 00:00:00

// or

MySql.Data.Types.MySqlDateTime myDate2 = new MySql.Data.Types.MySqlDateTime(new DateTime(2006,08,05,23,20,15));
System.Console.WriteLine(myDate2.ToString()); // 2006-08-05 23:20:15[/code]

The modified file can be accessed at /Types/MySqlDateTime.cs
For those who won’t re-build the connector themselves I have also uploaded a binary at /bin/net-2.0/Release/MySql.Data.dll

There is still a problem concerning the values saved into this type: for example an object of this type can report that it contains a valid date when it contains “2006-02-31 00:00:00″. This is wrong because February cannot have 31 days. So, the checking of validity of this class needs a change. Currently, the only invalid date is “0000-00-00″ (MySQL ZERO date).

I have decided to try and write a Flex library that will be used to connect Flex applications to MySQL natively.

Some of the current approches include consuming XML documents produced by other languages like PHP, JAVA and others.

I will make it expose methods like those found in MySQL Connector/NET.

The main motivation is to reduce the languages used in a single application (or package) and gaining more speed (not 100% sure on this though). Also I hope to gain more knowledge on Flex and ActionScript 3.

While using Connector/.NET to connect to MySQL I prefer accessing the DataReader fields using their names.

Like

[code lang="C#"]
string sCustomerName = dbReader.GetString("CustomerName") ;
int nSomeIntegerVariable = dbReader.GetInt32("AnIntegerField"); [/code]

I love doing it this way because I can reorder my columns without having to change the access code.

With the current connector, one should retreive the field Index (using the GetOrdinal() Method) and pass that ordinal (Index) to one of the accessors to get the value of the column.
I have been doing that but I found it cumbersome and decided to add some methods in the DataReader Class definition.

The methods I added are:
[code lang="C#"]
public bool GetBoolean(String name)
public byte GetByte(String name)
public long GetBytes(String name, long dataIndex, byte[] buffer, int bufferIndex, int length)
public char GetChar(String name)
public long GetChars(String name, long fieldOffset, char[] buffer, int bufferoffset, int length)
public String GetDataTypeName(String name)
public MySqlDateTime GetMySqlDateTime(String name)
public DateTime GetDateTime(String name)
public Decimal GetDecimal(String name)
public double GetDouble(String name)
public Type GetFieldType(String name)
public float GetFloat(String name)
public Guid GetGuid(String name)
public Int16 GetInt16(String name)
public Int32 GetInt32(String name)
public Int64 GetInt64(String name)
public String GetString(String name)
public TimeSpan GetTimeSpan(String name)
public object GetValue(String name)
public UInt16 GetUInt16(String name)
public UInt32 GetUInt32(String name)
public UInt64 GetUInt64(String name)
public bool IsDBNull(String name)[/code]

In the XML comments of each of these methods I added a line saying that
ordinal based lookups are faster.

The modified file can be accessed at
/dev/mysql/net/mysqlclient/datareader.cs
For those who won’t re-build the connector themselves I have also uploadead
a binary at
/dev/mysql/net/bin/net-2.0/Release/MySql.Data.dll