Created
June 4, 2013 17:16
-
-
Save LeeCampbell/5707761 to your computer and use it in GitHub Desktop.
KDB Client rewritten from sample Kx code to use more useful names.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//2012.06.07 fixed scoping of GUID | |
//2012.05.29 for use with kdb+v3.0, changed handshake and added Guid. boolean v6->vt tracks type capability. | |
//2012.01.26 refactored clamp into clampDT, for Date.DateTime() | |
//2012.01.25 rz() clamp datetime to valid range | |
//2010.11.17 Block sending new timetypes to version of kdb+ prior to v2.6 (use prior release of KdbClient.cs for older kdb+ versions) | |
// Max buffer size (default 64kB) used for reading is now a parameter to the KdbClient constructor | |
// Date, Month, Minute, Second, KTimeSpan are now serializable, implement IComparable | |
// and have default constructors for xml serialization. | |
// Added GetNullRepresentation(Type t) | |
//2010.08.05 Added KException for exceptions due to server error, authentication fail and func decode | |
//2010.01.14 Exposed static var e (Encoding) as public | |
//2010.01.12 Added support for unicode encoding, defaults to ASCII | |
//2010.01.11 Added null checks for IsNull for UDTs Date,Month,Minute,Second,KTimespan | |
//2010.01.04 Added new time types (timespan->KTimespan,timestamp->DateTime), drop writing kdb+ datetime | |
//2009.10.19 Limit reads to blocks of 64kB to reduce load on kernel memory | |
//2007.09.26 0Wz to MaxValue | |
//2006.10.05 truncate string GetValueAt null | |
//2006.09.29 GetNullRepresentation KdbClient.Date class(sync with KdbClient.java) | |
using System; | |
using System.IO; | |
using System.Net.Sockets; //csc KdbClient.cs given >q trade.q -port 5001 | |
namespace kx | |
{ | |
public class KdbClient : TcpClient | |
{ | |
/*public static void Main(string[]args){ | |
//KdbClient.ReceiveTimeout=1000; | |
//KdbClient KdbClient=new KdbClient("localhost",5010);KdbClient.k(".username.sub[`trade;`MSFT.O`IBM.N]");while(true){object Read=KdbClient.k();O(GetLength(GetValueAt(Read,2)));} | |
KdbClient KdbClient=new KdbClient("localhost",5001); | |
//KdbClient.e=System.Text.Encoding.UTF8; | |
//O("Unicode "+KdbClient.k("`$\"KdbClient\"$0x52616e627920426ac3b6726b6c756e64204142")); | |
//object[]FieldNames=new object[4];FieldNames[0]=TimeOfDay();FieldNames[1]="xx";FieldNames[2]=(double)93.5;FieldNames[3]=300;tm();for(int i=0;i<1000;++i)KdbClient.k("insert","trade",FieldNames);tm(); | |
//Flip Read=ToFlip(KdbClient.k("select sum price by sym from trade"));O("cols: "+GetLength(Read.FieldNames));O("rows: "+GetLength(Read.Values[0])); | |
KdbClient.Close(); | |
} | |
*/ | |
public static System.Text.Encoding e = System.Text.Encoding.ASCII; | |
private const int DefaultMaxBufferSize = 65536; | |
private const long Jan2000Ticks = (long) 8.64e11*730119; | |
private static readonly byte[] Gip = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; | |
static readonly object[] Nulls ={null,false,new Guid(),null,(byte)0,Int16.MinValue,Int32.MinValue,Int64.MinValue,(Single)Double.NaN,Double.NaN,' ',"",new DateTime(0), | |
new Month(Int32.MinValue),new Date(Int32.MinValue),new DateTime(0),new KTimespan(Int64.MinValue),new Minute(Int32.MinValue),new Second(Int32.MinValue),new TimeSpan(Int32.MinValue)}; | |
private readonly int _maxBufferSize = DefaultMaxBufferSize; | |
private readonly Stream _currentStream; | |
private readonly int _serverVersion; | |
byte[] _buffer; | |
private int _currentIndex; | |
private byte[] b; //Perhaps the current field buffer? -LC | |
private int j; //Perhaps the current field index? -LC | |
private bool a; //EOF flag? -LC | |
public KdbClient(string hostname, int port) | |
: this(hostname, port, Environment.UserName) { } | |
public KdbClient(string hostname, int port, string username) | |
: this(hostname, port, username, DefaultMaxBufferSize) { } | |
public KdbClient(string hostname, int port, string username, int maxBufferSize) | |
{ | |
_maxBufferSize = maxBufferSize; | |
Connect(hostname, port); | |
_currentStream = GetStream(); | |
_buffer = new byte[2 + username.Length]; | |
_currentIndex = 0; | |
Write(username + "\x3"); | |
_currentStream.Write(_buffer, 0, _currentIndex); | |
if (1 != _currentStream.Read(_buffer, 0, 1)) | |
{ | |
_buffer = new byte[1 + username.Length]; | |
Connect(hostname, port); | |
_currentStream = GetStream(); | |
_currentIndex = 0; | |
Write(username); | |
_currentStream.Write(_buffer, 0, _currentIndex); | |
if (1 != _currentStream.Read(_buffer, 0, 1)) | |
throw new KException("access"); | |
} | |
_serverVersion = Math.Min(_buffer[0], (byte)3); | |
} | |
public new void Close() | |
{ | |
_currentStream.Close(); | |
base.Close(); | |
} | |
public object k() | |
{ | |
ReadInto(b = new byte[8]); | |
a = b[0] == 1; | |
bool c = b[2] == 1; | |
j = 4; | |
ReadInto(b = new byte[ReadInt() - 8]); | |
if (c) | |
u(); | |
else | |
j = 0; | |
if (b[0] == 128) | |
{ | |
j = 1; | |
throw new KException(ReadString()); | |
} | |
return Read(); | |
} | |
public object k(object x) | |
{ | |
Write(1, x); return k(); | |
} | |
public object k(string s) | |
{ | |
return k(s.ToCharArray()); | |
} | |
public object k(string s, object x) | |
{ | |
object[] a = { s.ToCharArray(), x }; | |
return k(a); | |
} | |
public object k(string s, object x, object y) | |
{ | |
object[] a = { s.ToCharArray(), x, y }; | |
return k(a); | |
} | |
public object k(string s, object x, object y, object z) | |
{ | |
object[] a = { s.ToCharArray(), x, y, z }; | |
return k(a); | |
} | |
public void ks(String s) | |
{ | |
Write(0, s.ToCharArray()); | |
} | |
public void ks(String s, Object x) | |
{ | |
Object[] a = { s.ToCharArray(), x }; | |
Write(0, a); | |
} | |
public void ks(String s, Object x, Object y) | |
{ | |
Object[] a = { s.ToCharArray(), x, y }; | |
Write(0, a); | |
} | |
public static int GetLength(object source) | |
{ | |
return source is Dict | |
? GetLength(((Dict)source).x) | |
: source is Flip | |
? GetLength(((Flip)source).Values[0]) | |
: source is char[] | |
? e.GetBytes((char[])source).Length | |
: ((Array)source).Length; | |
} | |
public static object GetValueAt(object x, int i) | |
{ | |
object r = ((Array)x).GetValue(i); | |
return IsNull(r) ? null : r; | |
} | |
public static object GetNullRepresentation(Type t) | |
{ | |
for (int i = 0; i < Nulls.Length; i++) | |
if (Nulls[i] != null && t == Nulls[i].GetType()) | |
return Nulls[i]; | |
return null; | |
} | |
public static bool IsNull(object x) | |
{ | |
int t = -GetTypeIndex(x); | |
return t > 4 && x.Equals(Nulls[t]); | |
} | |
public static Flip ToFlip(object source) | |
{ | |
if (GetTypeIndex(source) == 98) //If source is Flip | |
return (Flip)source; | |
Dict d = (Dict)source; | |
Flip a = (Flip)d.x, b = (Flip)d.y; | |
int m = KdbClient.GetLength(a.FieldNames), n = KdbClient.GetLength(b.FieldNames); | |
var x = new string[m + n]; | |
Array.Copy(a.FieldNames, 0, x, 0, m); | |
Array.Copy(b.FieldNames, 0, x, m, n); | |
var y = new object[m + n]; | |
Array.Copy(a.Values, 0, y, 0, m); | |
Array.Copy(b.Values, 0, y, m, n); | |
return new Flip(new Dict(x, y)); | |
} | |
void u() | |
{ | |
int n = 0, r = 0, f = 0, s = 8, p = s; | |
short i = 0; | |
j = 0; | |
byte[] dst = new byte[ReadInt()]; | |
int d = j; | |
int[] aa = new int[256]; | |
while (s < dst.Length) | |
{ | |
if (i == 0) | |
{ | |
f = 0xff & (int)b[d++]; | |
i = 1; | |
} | |
if ((f & i) != 0) | |
{ | |
r = aa[0xff & (int)b[d++]]; | |
dst[s++] = dst[r++]; | |
dst[s++] = dst[r++]; | |
n = 0xff & (int)b[d++]; | |
for (int m = 0; m < n; m++) | |
dst[s + m] = dst[r + m]; | |
} | |
else | |
dst[s++] = b[d++]; | |
while (p < s - 1) | |
aa[(0xff & (int)dst[p]) ^ (0xff & (int)dst[p + 1])] = p++; | |
if ((f & i) != 0) | |
p = s += n; | |
i *= 2; | |
if (i == 256) | |
i = 0; | |
} | |
b = dst; | |
j = 8; | |
} | |
void Write(object x) | |
{ | |
int t = KdbClient.GetTypeIndex(x); Write((byte)t); if (t < 0) switch (t) | |
{ | |
case -1: Write((bool)x); return; | |
case -2: Write((Guid)x); return; | |
case -4: Write((byte)x); return; | |
case -5: Write((short)x); return; | |
case -6: Write((int)x); return; | |
case -7: Write((long)x); return; | |
case -8: Write((float)x); return; | |
case -9: Write((double)x); return; | |
case -10: Write((char)x); return; | |
case -11: Write((string)x); return; | |
case -12: Write((DateTime)x); return; | |
case -13: Write((Month)x); return; | |
case -14: Write((Date)x); return; | |
case -15: Write((DateTime)x); return; | |
case -16: Write((KTimespan)x); return; | |
case -17: Write((Minute)x); return; | |
case -18: Write((Second)x); return; | |
case -19: Write((TimeSpan)x); return; | |
} | |
if (t == 99) { Dict r = (Dict)x; Write(r.x); Write(r.y); return; } _buffer[_currentIndex++] = 0; if (t == 98) { Flip r = (Flip)x; _buffer[_currentIndex++] = 99; Write(r.FieldNames); Write(r.Values); return; } | |
Write(KdbClient.GetLength(x)); switch (t) | |
{ | |
case 0: foreach (object o in (object[])x) Write(o); return; | |
case 1: foreach (bool o in (bool[])x) Write(o); return; | |
case 2: foreach (Guid o in (Guid[])x) Write(o); return; | |
case 4: foreach (byte o in (byte[])x) Write(o); return; | |
case 5: foreach (short o in (short[])x) Write(o); return; | |
case 6: foreach (int o in (int[])x) Write(o); return; | |
case 7: foreach (long o in (long[])x) Write(o); return; | |
case 8: foreach (float o in (float[])x) Write(o); return; | |
case 9: foreach (double o in (double[])x) Write(o); return; | |
case 10: foreach (byte b in e.GetBytes((char[])x)) Write(b); return; | |
case 11: foreach (string o in (string[])x) Write(o); return; | |
case 12: foreach (DateTime o in (DateTime[])x) Write(o); return; | |
case 13: foreach (Month o in (Month[])x) Write(o); return; | |
case 14: foreach (Date o in (Date[])x) Write(o); return; | |
case 15: foreach (DateTime o in (DateTime[])x) Write(o); return; | |
case 16: foreach (KTimespan o in (KTimespan[])x) Write(o); return; | |
case 17: foreach (Minute o in (Minute[])x) Write(o); return; | |
case 18: foreach (Second o in (Second[])x) Write(o); return; | |
case 19: foreach (TimeSpan o in (TimeSpan[])x) Write(o); return; | |
} | |
} | |
void Write(int i, object x) | |
{ | |
int n = ByteSize(x) + 8; | |
_buffer = new byte[n]; | |
_buffer[0] = 1; | |
_buffer[1] = (byte)i; | |
_currentIndex = 4; | |
Write(n); | |
Write(x); | |
_currentStream.Write(_buffer, 0, n); | |
} | |
object Read() | |
{ | |
int i = 0, n, t = (sbyte)b[j++]; | |
if (t < 0) | |
switch (t) | |
{ | |
case -1: return ReadBoolean(); | |
case -2: return ReadGuid(); | |
case -4: return b[j++]; | |
case -5: return ReadShort(); | |
case -6: return ReadInt(); | |
case -7: return ReadLong(); | |
case -8: return ReadFloat(); | |
case -9: return ReadDouble(); | |
case -10: return ReadChar(); | |
case -11: return ReadString(); | |
case -12: return ReadDateTime(); | |
case -13: return ReadMonth(); | |
case -14: return ReadDate(); | |
case -15: return ReadDateTime2(); | |
case -16: return ReadKTimeSpan(); | |
case -17: return ReadMinute(); | |
case -18: return ReadSecond(); | |
case -19: return ReadTimeSpan(); | |
} | |
if (t > 99) | |
{ | |
if (t == 101 && b[j++] == 0) | |
return null; | |
throw new KException("func"); | |
} | |
if (t == 99) | |
return new Dict(Read(), Read()); | |
j++; | |
if (t == 98) | |
return new Flip((Dict)Read()); | |
n = ReadInt(); | |
switch (t) | |
{ | |
case 0: object[] L = new object[n]; for (; i < n; i++) L[i] = Read(); return L; | |
case 1: bool[] B = new bool[n]; for (; i < n; i++) B[i] = ReadBoolean(); return B; | |
case 2: { Guid[] G = new Guid[n]; for (; i < n; i++)G[i] = ReadGuid(); return G; } | |
case 4: { byte[] G = new byte[n]; for (; i < n; i++)G[i] = b[j++]; return G; } | |
case 5: short[] H = new short[n]; for (; i < n; i++) H[i] = ReadShort(); return H; | |
case 6: int[] I = new int[n]; for (; i < n; i++) I[i] = ReadInt(); return I; | |
case 7: long[] J = new long[n]; for (; i < n; i++) J[i] = ReadLong(); return J; | |
case 8: float[] E = new float[n]; for (; i < n; i++) E[i] = ReadFloat(); return E; | |
case 9: double[] F = new double[n]; for (; i < n; i++) F[i] = ReadDouble(); return F; | |
case 10: char[] C = e.GetChars(b, j, n); j += n; return C; | |
case 11: String[] S = new String[n]; for (; i < n; i++) S[i] = ReadString(); return S; | |
case 12: DateTime[] P = new DateTime[n]; for (; i < n; i++) P[i] = ReadDateTime(); return P; | |
case 13: Month[] M = new Month[n]; for (; i < n; i++) M[i] = ReadMonth(); return M; | |
case 14: Date[] D = new Date[n]; for (; i < n; i++) D[i] = ReadDate(); return D; | |
case 15: DateTime[] Z = new DateTime[n]; for (; i < n; i++) Z[i] = ReadDateTime2(); return Z; | |
case 16: KTimespan[] N = new KTimespan[n]; for (; i < n; i++) N[i] = ReadKTimeSpan(); return N; | |
case 17: Minute[] U = new Minute[n]; for (; i < n; i++) U[i] = ReadMinute(); return U; | |
case 18: Second[] V = new Second[n]; for (; i < n; i++) V[i] = ReadSecond(); return V; | |
case 19: TimeSpan[] T = new TimeSpan[n]; for (; i < n; i++) T[i] = ReadTimeSpan(); return T; | |
} | |
return null; | |
} | |
void Write(bool x) | |
{ | |
_buffer[_currentIndex++] = (byte)(x ? 1 : 0); | |
} | |
bool ReadBoolean() | |
{ | |
return 1 == b[j++]; | |
} | |
void Write(byte x) { _buffer[_currentIndex++] = x; } | |
byte ReadByte() { return b[j++]; } | |
void Write(short h) { _buffer[_currentIndex++] = (byte)h; _buffer[_currentIndex++] = (byte)(h >> 8); } | |
short ReadShort() { int x = b[j++], y = b[j++]; return (short)(a ? x & 0xff | y << 8 : x << 8 | y & 0xff); } | |
void Write(int i) { Write((short)i); Write((short)(i >> 16)); } | |
int ReadInt() { int x = ReadShort(), y = ReadShort(); return a ? x & 0xffff | y << 16 : x << 16 | y & 0xffff; } | |
void Write(Guid g) { byte[] b = g.ToByteArray(); if (_serverVersion < 3)throw new KException("Guid not valid pre kdb+3.0"); for (int i = 0; i < b.Length; i++)Write(b[Gip[i]]); } | |
Guid ReadGuid() { bool oa = a; a = false; int i = ReadInt(); short h1 = ReadShort(), h2 = ReadShort(); a = oa; byte[] b = new byte[8]; for (int j = 0; j < 8; j++)b[j] = ReadByte(); return new Guid(i, h1, h2, b); } | |
void Write(long j) { Write((int)j); Write((int)(j >> 32)); } | |
long ReadLong() { int x = ReadInt(), y = ReadInt(); return a ? x & 0xffffffffL | (long)y << 32 : (long)x << 32 | y & 0xffffffffL; } | |
void Write(float e) { byte[] b = BitConverter.GetBytes(e); foreach (byte i in b)Write(i); } | |
float ReadFloat() | |
{ | |
byte c; float e; | |
if (!a) { c = b[j]; b[j] = b[j + 3]; b[j + 3] = c; c = b[j + 1]; b[j + 1] = b[j + 2]; b[j + 2] = c; } e = BitConverter.ToSingle(b, j); j += 4; return e; | |
} | |
void Write(double f) { Write(BitConverter.DoubleToInt64Bits(f)); } | |
double ReadDouble() { return BitConverter.Int64BitsToDouble(ReadLong()); } | |
void Write(char c) { Write((byte)c); } | |
char ReadChar() { return (char)(b[j++] & 0xff); } | |
void Write(string s) { byte[] b = e.GetBytes(s); foreach (byte i in b)Write(i); _buffer[_currentIndex++] = 0; } | |
string ReadString() { int k = j; for (; b[j] != 0; ++j);string s = e.GetString(b, k, j - k); j++; return s; } | |
void Write(Date d) { Write(d.i); } | |
Date ReadDate() { return new Date(ReadInt()); } | |
void Write(Minute u) { Write(u.i); } | |
Minute ReadMinute() { return new Minute(ReadInt()); } | |
void Write(Month m) { Write(m.i); } | |
Month ReadMonth() { return new Month(ReadInt()); } | |
void Write(Second v) { Write(v.i); } | |
Second ReadSecond() { return new Second(ReadInt()); } | |
void Write(TimeSpan t) { if (_serverVersion < 1)throw new KException("Timespan not valid pre kdb+2.6"); Write(IsNull(t) ? Int32.MinValue : (int)(t.Ticks / 10000)); } | |
TimeSpan ReadTimeSpan() { int i = ReadInt(); return new TimeSpan(IsNull(i) ? Int32.MinValue : 10000L * i); } | |
void Write(DateTime p) { if (_serverVersion < 1)throw new KException("Timestamp not valid pre kdb+2.6"); Write(IsNull(p) ? Int64.MinValue : (100 * (p.Ticks - Jan2000Ticks))); } | |
DateTime ReadDateTime() { long j = ReadLong(), d = j < 0 ? (j + 1) / 100 - 1 : j / 100; DateTime p = new DateTime(j == Int64.MinValue ? 0 : Jan2000Ticks + d); return p; } | |
DateTime ReadDateTime2() { double f = ReadDouble(); return Double.IsInfinity(f) ? (f < 0 ? DateTime.MinValue : DateTime.MaxValue) : new DateTime(IsNull(f) ? 0 : ClampTickValue(10000 * (long)Math.Round(8.64e7 * f) + Jan2000Ticks)); } | |
void Write(KTimespan t) { Write(IsNull(t) ? Int64.MinValue : (t.t.Ticks * 100)); } | |
KTimespan ReadKTimeSpan() { return new KTimespan(ReadLong()); } | |
void ReadInto(byte[] buffer) | |
{ | |
int i = 0, j, n = buffer.Length; | |
for (; i < n; i += j) | |
if (0 == (j = _currentStream.Read(buffer, i, Math.Min(_maxBufferSize, n - i)))) | |
throw new Exception("ReadInto"); | |
} | |
static long ClampTickValue(long tick) | |
{ | |
return Math.Min( | |
Math.Max(tick, DateTime.MinValue.Ticks), | |
DateTime.MaxValue.Ticks); | |
} | |
static int IndexOf(string[] x, string y) | |
{ | |
int i = 0; | |
for (; i < x.Length && !x[i].Equals(y); ) | |
++i; | |
return i; | |
} | |
static int ByteSize(object x) | |
{ | |
int t = GetTypeIndex(x); | |
if (t == 99) //FieldNames is Dict | |
return 1 + ByteSize(((Dict)x).x) + ByteSize(((Dict)x).y); | |
if (t == 98) //FieldNames is Flip | |
return 3 + ByteSize(((Flip)x).FieldNames) + ByteSize(((Flip)x).Values); | |
if (t < 0) | |
return t == -11 //FieldNames is string | |
? 2 + CountBytesToNullTerminator((string)x) | |
: 1 + TypeSizes[-t]; | |
var j = 6; | |
var n = KdbClient.GetLength(x); | |
if (t == 0) | |
for (var i = 0; i < n; ++i) | |
j += ByteSize(((object[])x)[i]); | |
else | |
j += n * TypeSizes[t]; | |
return j; | |
} | |
static readonly int[] TypeSizes = | |
{ | |
0, //[0] (place holder) | |
1, //[1] bool | |
16, //[2] GUID | |
0, //[3] (place holder) | |
1, //[4] byte | |
2, //[5] short | |
4, //[6] int | |
8, //[7] long | |
4, //[8] float | |
8, //[9] double | |
1, //[10] char | |
0, //[11] string (calculated) | |
8, //[12] DateTime | |
4, //[13] Month | |
4, //[14] Date | |
8, //[15] DateTime (duplicated) | |
8, //[16] KTimespan | |
4, //[17] Minute | |
4, //[18] Second | |
4 //[19] TimeSpan | |
}; | |
static int GetTypeIndex(object x) | |
{ | |
return x is bool ? -1 | |
: x is Guid ? -2 | |
: x is byte ? -4 | |
: x is short ? -5 | |
: x is int ? -6 | |
: x is long ? -7 | |
: x is float ? -8 | |
: x is double ? -9 | |
: x is char ? -10 | |
: x is string ? -11 | |
: x is DateTime ? -12 | |
: x is Month ? -13 | |
: x is Date ? -14 | |
: x is DateTime ? -15 //Already captured by -12? -LC | |
: x is KTimespan ? -16 | |
: x is Minute ? -17 | |
: x is Second ? -18 | |
: x is TimeSpan ? -19 | |
: x is bool[] ? 1 | |
: x is Guid[] ? 2 | |
: x is byte[] ? 4 | |
: x is short[] ? 5 | |
: x is int[] ? 6 | |
: x is long[] ? 7 | |
: x is float[] ? 8 | |
: x is double[] ? 9 | |
: x is char[] ? 10 | |
: x is DateTime[] ? 12 | |
: x is DateTime[] ? 15 //Already captured by 12? -LC | |
: x is KTimespan[] ? 16 | |
: x is TimeSpan[] ? 19 | |
: x is Flip ? 98 | |
: x is Dict ? 99 | |
: 0; | |
} | |
static string PadInt(int i) | |
{ | |
return String.Format("{0:00}", i); | |
} | |
static int CountBytesToNullTerminator(string s) | |
{ | |
int i = s.IndexOf('\0'); | |
i = -1 < i ? i : s.Length; | |
return e.GetBytes(s.Substring(0, i)).Length; | |
} | |
public class Dict | |
{ | |
public object x; | |
public object y; | |
public Dict(object X, object Y) | |
{ | |
x = X; | |
y = Y; | |
} | |
} | |
public class Flip | |
{ | |
public string[] FieldNames; | |
public object[] Values; | |
public Flip(Dict source) | |
{ | |
FieldNames = (string[])source.x; | |
Values = (object[])source.y; | |
} | |
public object Value(string s) | |
{ | |
return Values[IndexOf(FieldNames, s)]; | |
} | |
} | |
[Serializable] | |
public class Date : IComparable | |
{ | |
public int i; private Date() { }public Date(int x) { i = x; } | |
public DateTime DateTime() { return i == -int.MaxValue ? System.DateTime.MinValue : i == int.MaxValue ? System.DateTime.MaxValue : new DateTime(i == Int32.MinValue ? 0L : ClampTickValue((long)8.64e11 * i + Jan2000Ticks)); } | |
public Date(long x) { i = x == 0L ? Int32.MinValue : (int)(x / (long)8.64e11) - 730119; }public Date(DateTime z) : this(z.Ticks) { } | |
public override string ToString() { return i == Int32.MinValue ? "" : this.DateTime().ToString("d"); } | |
public override bool Equals(object o) { if (o == null)return false; if (this.GetType() != o.GetType())return false; Date d = (Date)o; return i == d.i; } | |
public override int GetHashCode() { return i; } | |
public int CompareTo(object o) { if (o == null)return 1; Date other = o as Date; if (other == null)return 1; return i.CompareTo(other.i); } | |
} | |
[Serializable] | |
public class Month : IComparable | |
{ | |
public int i; private Month() { }public Month(int x) { i = x; } | |
public override string ToString() { int m = 24000 + i, y = m / 12; return i == Int32.MinValue ? "" : PadInt(y / 100) + PadInt(y % 100) + "-" + PadInt(1 + m % 12); } | |
public override bool Equals(object o) { if (o == null)return false; if (this.GetType() != o.GetType())return false; Month m = (Month)o; return i == m.i; } | |
public override int GetHashCode() { return i; } | |
public int CompareTo(object o) { if (o == null)return 1; Month other = o as Month; if (other == null)return 1; return i.CompareTo(other.i); } | |
} | |
[Serializable] | |
public class Minute : IComparable | |
{ | |
public int i; private Minute() { }public Minute(int x) { i = x; } | |
public override string ToString() { return i == Int32.MinValue ? "" : PadInt(i / 60) + ":" + PadInt(i % 60); } | |
public override bool Equals(object o) { if (o == null)return false; if (this.GetType() != o.GetType())return false; Minute m = (Minute)o; return i == m.i; } | |
public override int GetHashCode() { return i; } | |
public int CompareTo(object o) { if (o == null)return 1; Minute other = o as Minute; if (other == null)return 1; return i.CompareTo(other.i); } | |
} | |
[Serializable] | |
public class Second : IComparable | |
{ | |
public int i; private Second() { }public Second(int x) { i = x; } | |
public override string ToString() { return i == Int32.MinValue ? "" : new Minute(i / 60).ToString() + ':' + PadInt(i % 60); } | |
public override bool Equals(object o) { if (o == null)return false; if (this.GetType() != o.GetType())return false; Second s = (Second)o; return i == s.i; } | |
public override int GetHashCode() { return i; } | |
public int CompareTo(object o) { if (o == null)return 1; Second other = o as Second; if (other == null)return 1; return i.CompareTo(other.i); } | |
} | |
[Serializable] | |
public class KTimespan : IComparable | |
{ | |
public TimeSpan t; private KTimespan() { }public KTimespan(long x) { t = new TimeSpan(x == Int64.MinValue ? Int64.MinValue : x / 100); } | |
public override string ToString() { return IsNull(t) ? "" : t.ToString(); } | |
public override bool Equals(object o) { if (o == null)return false; if (this.GetType() != o.GetType())return false; KTimespan n = (KTimespan)o; return t.Ticks == n.t.Ticks; } | |
public override int GetHashCode() { return t.GetHashCode(); } | |
public int CompareTo(object o) { if (o == null)return 1; KTimespan other = o as KTimespan; if (other == null)return 1; return t.CompareTo(other.t); } | |
} | |
} | |
public class KException : Exception | |
{ | |
public KException() { } | |
public KException(string message) : base(message) { } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment