// Copyright (C) 2004 MySQL AB
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as published by
// the Free Software Foundation
//
// There are special exceptions to the terms and conditions of the GPL
// as it is applied to this software. View the full text of the
// exception in file EXCEPTIONS in the directory of this software
// distribution.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Data;
using MySql.Data.MySqlClient;
namespace MySql.Data.Types
{
///
/// Summary description for MySqlDateTime.
///
public class MySqlDateTime : MySqlValue, IConvertible
{
private DateTime mValue;
private bool isZero;
internal MySqlDateTime()
{
dbType = DbType.DateTime;
mySqlDbType = MySqlDbType.Datetime;
}
internal MySqlDateTime(MySqlDbType type) : this()
{
if (type == MySqlDbType.Date)
dbType = DbType.Date;
else
dbType = DbType.DateTime;
mySqlDbType = type;
}
internal MySqlDateTime(DateTime val, MySqlDbType type) : this(type)
{
mValue = val;
}
/// Indicates if this value is zero
public bool IsZero
{
get { return isZero; }
}
internal override void SerializeBinary(PacketWriter writer)
{
Packet p = new Packet(false);
if (mySqlDbType == MySqlDbType.Timestamp)
writer.WriteByte( 11 );
else
writer.WriteByte( 7 );
writer.WriteInteger( mValue.Year, 2 );
writer.WriteByte( (byte)mValue.Month );
writer.WriteByte( (byte)mValue.Day );
if (mySqlDbType == MySqlDbType.Date)
{
writer.WriteByte( 0 );
writer.WriteByte( 0 );
writer.WriteByte( 0 );
}
else
{
writer.WriteByte( (byte)mValue.Hour );
writer.WriteByte( (byte)mValue.Minute );
writer.WriteByte( (byte)mValue.Second );
}
if (mySqlDbType == MySqlDbType.Timestamp)
writer.WriteInteger( mValue.Millisecond, 4 );
}
/// Returns this value as byte[]
public override byte[] ToBytes()
{
Packet p = new Packet(false);
byte len = 11;
if (mySqlDbType == MySqlDbType.Date)
len = 7;
p.WriteByte( len );
p.WriteInteger( mValue.Year, 2 );
p.WriteByte( (byte)mValue.Month );
p.WriteByte( (byte)mValue.Day );
if (mySqlDbType == MySqlDbType.Date)
{
p.WriteByte( 0 );
p.WriteByte( 0 );
p.WriteByte( 0 );
}
else
{
p.WriteByte( (byte)mValue.Hour );
p.WriteByte( (byte)mValue.Minute );
p.WriteByte( (byte)mValue.Second );
}
if (mySqlDbType == MySqlDbType.Timestamp)
p.WriteInteger( mValue.Millisecond, 4 );
byte[] buff = new byte[len+1];
Array.Copy( p.GetBuffer(), 0, buff, 0, len+1 );
return buff;
}
internal override DbType DbType
{
get
{
switch (mySqlDbType)
{
case MySqlDbType.Date:
case MySqlDbType.Newdate:
return DbType.Date;
}
return DbType.DateTime;
}
}
internal override string GetMySqlTypeName()
{
switch (mySqlDbType)
{
case MySqlDbType.Date: return "DATE";
case MySqlDbType.Newdate: return "NEWDATE";
case MySqlDbType.Timestamp: return "TIMESTAMP";
}
return "DATETIME";
}
internal override object ValueAsObject
{
get { return mValue; }
set { mValue = Convert.ToDateTime(value); }
}
/// Returns this value as a DateTime
public DateTime Value
{
get { return mValue; }
set { mValue = value; }
}
/// Parses a string into this value
///
public override void Parse(string s)
{
mValue = DateTime.Parse(s);
}
internal void ParseMySql( string s, bool is41 )
{
isZero = false;
switch (mySqlDbType)
{
case MySqlDbType.Date:
if (s == "0000-00-00") isZero = true;
else mValue = DateTime.ParseExact( s, "yyyy-MM-dd", System.Globalization.DateTimeFormatInfo.InvariantInfo );
break;
case MySqlDbType.Datetime:
if (s == "0000-00-00 00:00:00") isZero = true;
else mValue = DateTime.ParseExact( s, "yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo );
break;
case MySqlDbType.Timestamp:
// MySql 4.1.0 and later use DateTime format for timestamp
if (is41)
{
if (s == "0000-00-00 00:00:00") isZero = true;
else mValue = DateTime.ParseExact( s, "yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo );
return;
}
string pattern;
switch (s.Length)
{
case 2: pattern = "yy"; break;
case 4: pattern = "yyMM"; break;
case 6: pattern = "yyMMdd"; break;
case 8: pattern = "yyyyMMdd"; break;
case 10: pattern = "yyMMddHHmm"; break;
case 12: pattern = "yyMMddHHmmss"; break;
case 14:
default: pattern = "yyyyMMddHHmmss"; break;
}
if (s.Replace("0","").Length == 0) isZero = true;
else
mValue = DateTime.ParseExact( s, pattern, System.Globalization.DateTimeFormatInfo.InvariantInfo );
break;
}
}
internal override Type SystemType
{
get { return typeof(DateTime); }
}
internal override long SetBinaryData(Packet packet)
{
long bufLength = 0;
bufLength = packet.ReadByte();
if (bufLength == 0)
IsNull = true;
else if (bufLength == 4)
mValue = new DateTime( packet.ReadInteger(2), packet.ReadByte(),
packet.ReadByte() );
else if (bufLength == 7)
mValue = new DateTime( packet.ReadInteger(2), packet.ReadByte(),
packet.ReadByte(), packet.ReadByte(), packet.ReadByte(),
packet.ReadByte() );
else if (bufLength == 11)
mValue = new DateTime( packet.ReadInteger(2), packet.ReadByte(),
packet.ReadByte(), packet.ReadByte(), packet.ReadByte(),
packet.ReadByte(), packet.ReadInteger(4) / 1000000 );
return bufLength;
}
/// Returns a MySQL specific string representation of this value
public override string ToString()
{
if (mySqlDbType == MySqlDbType.Date)
return IsZero ? "0000-00-00" : Value.ToString("yyyy-MM-dd");
return IsZero ? "0000-00-00 00:00:00" : Value.ToString( "yyyy-MM-dd HH:mm:ss" );
}
internal string ToMySqlString(bool is41)
{
switch (mySqlDbType)
{
case MySqlDbType.Date:
return mValue.ToString("yyyy-MM-dd");
case MySqlDbType.Datetime:
return mValue.ToString("yyyy-MM-dd HH:mm:ss");
case MySqlDbType.Timestamp:
if (is41)
return mValue.ToString("yyyy-MM-dd HH:mm:ss");
else
return mValue.ToString("yyyyMMddHHmmss");
}
return mValue.ToString();
}
#region IConvertible Members
ulong IConvertible.ToUInt64(IFormatProvider provider)
{
return Convert.ToUInt64( mValue );
}
sbyte IConvertible.ToSByte(IFormatProvider provider)
{
return Convert.ToSByte( mValue );
}
double IConvertible.ToDouble(IFormatProvider provider)
{
return Convert.ToDouble( mValue );
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
return mValue;
}
float IConvertible.ToSingle(IFormatProvider provider)
{
return Convert.ToSingle( mValue );
}
bool IConvertible.ToBoolean(IFormatProvider provider)
{
return Convert.ToBoolean( mValue );
}
int IConvertible.ToInt32(IFormatProvider provider)
{
return Convert.ToInt32( mValue );
}
ushort IConvertible.ToUInt16(IFormatProvider provider)
{
return Convert.ToUInt16( mValue );
}
short IConvertible.ToInt16(IFormatProvider provider)
{
return Convert.ToInt16( mValue );
}
string IConvertible.ToString(IFormatProvider provider)
{
return ToString();
}
byte IConvertible.ToByte(IFormatProvider provider)
{
return Convert.ToByte( mValue );
}
char IConvertible.ToChar(IFormatProvider provider)
{
return Convert.ToChar( mValue );
}
long IConvertible.ToInt64(IFormatProvider provider)
{
return Convert.ToInt64( mValue );
}
TypeCode IConvertible.GetTypeCode()
{
return TypeCode.Object;
}
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal( mValue );
}
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
return null;
}
uint IConvertible.ToUInt32(IFormatProvider provider)
{
return Convert.ToUInt32( mValue );
}
#endregion
}
}