|
Since you use specialised fonts, I'd suggest to try the Graphics.DrawString() method for drawing it into a e.g. bitmap.
|
|
|
|
|
Please use the following code,there is two classes and use can pass the barcodeString which you create the image or bitmap from string.
This function return you the Code128 format barcodes
using System;
using System.Text;
namespace BarcodeAPP
{
public enum CodeSet
{
CodeA
,CodeB
// ,CodeC // not supported
}
/// <summary>
/// Represent the set of code values to be output into barcode form
/// </summary>
public class Code128Content
{
private int[] mCodeList;
/// <summary>
/// Create content based on a string of ASCII data
/// </summary>
/// <param name="AsciiData">the string that should be represented</param>
public Code128Content( string AsciiData )
{
mCodeList = StringToCode128(AsciiData);
}
/// <summary>
/// Provides the Code128 code values representing the object's string
/// </summary>
public int[] Codes
{
get
{
return mCodeList;
}
}
/// <summary>
/// Transform the string into integers representing the Code128 codes
/// necessary to represent it
/// </summary>
/// <param name="AsciiData">String to be encoded</param>
/// <returns>Code128 representation</returns>
private int[] StringToCode128( string AsciiData )
{
// turn the string into ascii byte data
byte[] asciiBytes = Encoding.ASCII.GetBytes( AsciiData );
// decide which codeset to start with
Code128Code.CodeSetAllowed csa1 = asciiBytes.Length>0 ? Code128Code.CodesetAllowedForChar( asciiBytes[0] ) : Code128Code.CodeSetAllowed.CodeAorB;
Code128Code.CodeSetAllowed csa2 = asciiBytes.Length>0 ? Code128Code.CodesetAllowedForChar( asciiBytes[1] ) : Code128Code.CodeSetAllowed.CodeAorB;
CodeSet currcs = GetBestStartSet(csa1,csa2);
// set up the beginning of the barcode
System.Collections.ArrayList codes = new System.Collections.ArrayList(asciiBytes.Length + 3); // assume no codeset changes, account for start, checksum, and stop
codes.Add(Code128Code.StartCodeForCodeSet(currcs));
// add the codes for each character in the string
for (int i = 0; i < asciiBytes.Length; i++)
{
int thischar = asciiBytes[i];
int nextchar = asciiBytes.Length>(i+1) ? asciiBytes[i+1] : -1;
codes.AddRange( Code128Code.CodesForChar(thischar, nextchar, ref currcs) );
}
// calculate the check digit
int checksum = (int)(codes[0]);
for (int i = 1; i < codes.Count; i++)
{
checksum += i * (int)(codes[i]);
}
codes.Add( checksum % 103 );
codes.Add( Code128Code.StopCode() );
int[] result = codes.ToArray(typeof(int)) as int[];
return result;
}
/// <summary>
/// Determines the best starting code set based on the the first two
/// characters of the string to be encoded
/// </summary>
/// <param name="csa1">First character of input string</param>
/// <param name="csa2">Second character of input string</param>
/// <returns>The codeset determined to be best to start with</returns>
private CodeSet GetBestStartSet( Code128Code.CodeSetAllowed csa1, Code128Code.CodeSetAllowed csa2 )
{
int vote = 0;
vote += (csa1==Code128Code.CodeSetAllowed.CodeA) ? 1 : 0;
vote += (csa1==Code128Code.CodeSetAllowed.CodeB) ? -1 : 0;
vote += (csa2==Code128Code.CodeSetAllowed.CodeA) ? 1 : 0;
vote += (csa2==Code128Code.CodeSetAllowed.CodeB) ? -1 : 0;
return (vote>0) ? CodeSet.CodeA : CodeSet.CodeB; // ties go to codeB due to my own prejudices
}
}
/// <summary>
/// Static tools for determining codes for individual characters in the content
/// </summary>
public static class Code128Code
{
#region Constants
private const int cSHIFT = 98;
private const int cCODEA = 101;
private const int cCODEB = 100;
private const int cSTARTA = 103;
private const int cSTARTB = 104;
private const int cSTOP = 106;
#endregion
/// <summary>
/// Get the Code128 code value(s) to represent an ASCII character, with
/// optional look-ahead for length optimization
/// </summary>
/// <param name="CharAscii">The ASCII value of the character to translate</param>
/// <param name="LookAheadAscii">The next character in sequence (or -1 if none)</param>
/// <param name="CurrCodeSet">The current codeset, that the returned codes need to follow;
/// if the returned codes change that, then this value will be changed to reflect it</param>
/// <returns>An array of integers representing the codes that need to be output to produce the
/// given character</returns>
public static int[] CodesForChar(int CharAscii, int LookAheadAscii, ref CodeSet CurrCodeSet)
{
int[] result;
int shifter = -1;
if (!CharCompatibleWithCodeset(CharAscii,CurrCodeSet))
{
// if we have a lookahead character AND if the next character is ALSO not compatible
if ( (LookAheadAscii != -1) && !CharCompatibleWithCodeset(LookAheadAscii,CurrCodeSet) )
{
// we need to switch code sets
switch (CurrCodeSet)
{
case CodeSet.CodeA:
shifter = cCODEB;
CurrCodeSet = CodeSet.CodeB;
break;
case CodeSet.CodeB:
shifter = cCODEA;
CurrCodeSet = CodeSet.CodeA;
break;
}
}
else
{
// no need to switch code sets, a temporary SHIFT will suffice
shifter = cSHIFT;
}
}
if (shifter!=-1)
{
result = new int[2];
result[0] = shifter;
result[1] = CodeValueForChar(CharAscii);
}
else
{
result = new int[1];
result[0] = CodeValueForChar(CharAscii);
}
return result;
}
/// <summary>
/// Tells us which codesets a given character value is allowed in
/// </summary>
/// <param name="CharAscii">ASCII value of character to look at</param>
/// <returns>Which codeset(s) can be used to represent this character</returns>
public static CodeSetAllowed CodesetAllowedForChar(int CharAscii)
{
if (CharAscii>=32 && CharAscii<=95)
{
return CodeSetAllowed.CodeAorB;
}
else
{
return (CharAscii<32) ? CodeSetAllowed.CodeA : CodeSetAllowed.CodeB;
}
}
/// <summary>
/// Determine if a character can be represented in a given codeset
/// </summary>
/// <param name="CharAscii">character to check for</param>
/// <param name="currcs">codeset context to test</param>
/// <returns>true if the codeset contains a representation for the ASCII character</returns>
public static bool CharCompatibleWithCodeset(int CharAscii, CodeSet currcs)
{
CodeSetAllowed csa = CodesetAllowedForChar(CharAscii);
return csa==CodeSetAllowed.CodeAorB
|| (csa==CodeSetAllowed.CodeA && currcs==CodeSet.CodeA)
|| (csa==CodeSetAllowed.CodeB && currcs==CodeSet.CodeB);
}
/// <summary>
/// Gets the integer code128 code value for a character (assuming the appropriate code set)
/// </summary>
/// <param name="CharAscii">character to convert</param>
/// <returns>code128 symbol value for the character</returns>
public static int CodeValueForChar(int CharAscii)
{
return (CharAscii>=32) ? CharAscii-32 : CharAscii+64;
}
/// <summary>
/// Return the appropriate START code depending on the codeset we want to be in
/// </summary>
/// <param name="cs">The codeset you want to start in</param>
/// <returns>The code128 code to start a barcode in that codeset</returns>
public static int StartCodeForCodeSet(CodeSet cs)
{
return cs==CodeSet.CodeA ? cSTARTA : cSTARTB;
}
/// <summary>
/// Return the Code128 stop code
/// </summary>
/// <returns>the stop code</returns>
public static int StopCode()
{
return cSTOP;
}
/// <summary>
/// Indicates which code sets can represent a character -- CodeA, CodeB, or either
/// </summary>
public enum CodeSetAllowed
{
CodeA,
CodeB,
CodeAorB
}
}
}
-------------------------------------------------------------------------------------
secode class is
using System;
using System.Drawing;
using System.Diagnostics;
namespace BarcodeAPP
{
/// <summary>
/// Summary description for Code128Rendering.
/// </summary>
public static class Code128Rendering
{
#region Code patterns
// in principle these rows should each have 6 elements
// however, the last one -- STOP -- has 7. The cost of the
// extra integers is trivial, and this lets the code flow
// much more elegantly
private static readonly int[,] cPatterns =
{
{2,1,2,2,2,2,0,0}, // 0
{2,2,2,1,2,2,0,0}, // 1
{2,2,2,2,2,1,0,0}, // 2
{1,2,1,2,2,3,0,0}, // 3
{1,2,1,3,2,2,0,0}, // 4
{1,3,1,2,2,2,0,0}, // 5
{1,2,2,2,1,3,0,0}, // 6
{1,2,2,3,1,2,0,0}, // 7
{1,3,2,2,1,2,0,0}, // 8
{2,2,1,2,1,3,0,0}, // 9
{2,2,1,3,1,2,0,0}, // 10
{2,3,1,2,1,2,0,0}, // 11
{1,1,2,2,3,2,0,0}, // 12
{1,2,2,1,3,2,0,0}, // 13
{1,2,2,2,3,1,0,0}, // 14
{1,1,3,2,2,2,0,0}, // 15
{1,2,3,1,2,2,0,0}, // 16
{1,2,3,2,2,1,0,0}, // 17
{2,2,3,2,1,1,0,0}, // 18
{2,2,1,1,3,2,0,0}, // 19
{2,2,1,2,3,1,0,0}, // 20
{2,1,3,2,1,2,0,0}, // 21
{2,2,3,1,1,2,0,0}, // 22
{3,1,2,1,3,1,0,0}, // 23
{3,1,1,2,2,2,0,0}, // 24
{3,2,1,1,2,2,0,0}, // 25
{3,2,1,2,2,1,0,0}, // 26
{3,1,2,2,1,2,0,0}, // 27
{3,2,2,1,1,2,0,0}, // 28
{3,2,2,2,1,1,0,0}, // 29
{2,1,2,1,2,3,0,0}, // 30
{2,1,2,3,2,1,0,0}, // 31
{2,3,2,1,2,1,0,0}, // 32
{1,1,1,3,2,3,0,0}, // 33
{1,3,1,1,2,3,0,0}, // 34
{1,3,1,3,2,1,0,0}, // 35
{1,1,2,3,1,3,0,0}, // 36
{1,3,2,1,1,3,0,0}, // 37
{1,3,2,3,1,1,0,0}, // 38
{2,1,1,3,1,3,0,0}, // 39
{2,3,1,1,1,3,0,0}, // 40
{2,3,1,3,1,1,0,0}, // 41
{1,1,2,1,3,3,0,0}, // 42
{1,1,2,3,3,1,0,0}, // 43
{1,3,2,1,3,1,0,0}, // 44
{1,1,3,1,2,3,0,0}, // 45
{1,1,3,3,2,1,0,0}, // 46
{1,3,3,1,2,1,0,0}, // 47
{3,1,3,1,2,1,0,0}, // 48
{2,1,1,3,3,1,0,0}, // 49
{2,3,1,1,3,1,0,0}, // 50
{2,1,3,1,1,3,0,0}, // 51
{2,1,3,3,1,1,0,0}, // 52
{2,1,3,1,3,1,0,0}, // 53
{3,1,1,1,2,3,0,0}, // 54
{3,1,1,3,2,1,0,0}, // 55
{3,3,1,1,2,1,0,0}, // 56
{3,1,2,1,1,3,0,0}, // 57
{3,1,2,3,1,1,0,0}, // 58
{3,3,2,1,1,1,0,0}, // 59
{3,1,4,1,1,1,0,0}, // 60
{2,2,1,4,1,1,0,0}, // 61
{4,3,1,1,1,1,0,0}, // 62
{1,1,1,2,2,4,0,0}, // 63
{1,1,1,4,2,2,0,0}, // 64
{1,2,1,1,2,4,0,0}, // 65
{1,2,1,4,2,1,0,0}, // 66
{1,4,1,1,2,2,0,0}, // 67
{1,4,1,2,2,1,0,0}, // 68
{1,1,2,2,1,4,0,0}, // 69
{1,1,2,4,1,2,0,0}, // 70
{1,2,2,1,1,4,0,0}, // 71
{1,2,2,4,1,1,0,0}, // 72
{1,4,2,1,1,2,0,0}, // 73
{1,4,2,2,1,1,0,0}, // 74
{2,4,1,2,1,1,0,0}, // 75
{2,2,1,1,1,4,0,0}, // 76
{4,1,3,1,1,1,0,0}, // 77
{2,4,1,1,1,2,0,0}, // 78
{1,3,4,1,1,1,0,0}, // 79
{1,1,1,2,4,2,0,0}, // 80
{1,2,1,1,4,2,0,0}, // 81
{1,2,1,2,4,1,0,0}, // 82
{1,1,4,2,1,2,0,0}, // 83
{1,2,4,1,1,2,0,0}, // 84
{1,2,4,2,1,1,0,0}, // 85
{4,1,1,2,1,2,0,0}, // 86
{4,2,1,1,1,2,0,0}, // 87
{4,2,1,2,1,1,0,0}, // 88
{2,1,2,1,4,1,0,0}, // 89
{2,1,4,1,2,1,0,0}, // 90
{4,1,2,1,2,1,0,0}, // 91
{1,1,1,1,4,3,0,0}, // 92
{1,1,1,3,4,1,0,0}, // 93
{1,3,1,1,4,1,0,0}, // 94
{1,1,4,1,1,3,0,0}, // 95
{1,1,4,3,1,1,0,0}, // 96
{4,1,1,1,1,3,0,0}, // 97
{4,1,1,3,1,1,0,0}, // 98
{1,1,3,1,4,1,0,0}, // 99
{1,1,4,1,3,1,0,0}, // 100
{3,1,1,1,4,1,0,0}, // 101
{4,1,1,1,3,1,0,0}, // 102
{2,1,1,4,1,2,0,0}, // 103
{2,1,1,2,1,4,0,0}, // 104
{2,1,1,2,3,2,0,0}, // 105
{2,3,3,1,1,1,2,0} // 106
};
#endregion Code patterns
private const int cQuietWidth = 10;
/// <summary>
/// Make an image of a Code128 barcode for a given string
/// </summary>
/// <param name="InputData">Message to be encoded</param>
/// <param name="BarWeight">Base thickness for bar width (1 or 2 works well)</param>
/// <param name="AddQuietZone">Add required horiz margins (use if output is tight)</param>
/// <returns>An Image of the Code128 barcode representing the message</returns>
public static Image MakeBarcodeImage(string InputData, int BarWeight, bool AddQuietZone)
{
// get the Code128 codes to represent the message
Code128Content content = new Code128Content(InputData);
int[] codes = content.Codes;
int width, height;
width = ((codes.Length - 3) * 11 + 35) * BarWeight;
height = Convert.ToInt32(System.Math.Ceiling(Convert.ToSingle(width) * .22F));
if (AddQuietZone)
{
width += 2 * cQuietWidth * BarWeight; // on both sides
}
// get surface to draw on
Image myimg = new System.Drawing.Bitmap(width, height);
using (Graphics gr = Graphics.FromImage(myimg))
{
// set to white so we don't have to fill the spaces with white
gr.FillRectangle(System.Drawing.Brushes.White, 0, 0, width, height);
// skip quiet zone
int cursor = AddQuietZone ? cQuietWidth * BarWeight : 0;
for (int codeidx = 0; codeidx < codes.Length; codeidx++)
{
int code = codes[codeidx];
// take the bars two at a time: a black and a white
for (int bar = 0; bar < 8; bar += 2)
{
int barwidth = cPatterns[code, bar] * BarWeight;
int spcwidth = cPatterns[code, bar + 1] * BarWeight;
// if width is zero, don't try to draw it
if (barwidth > 0)
{
gr.FillRectangle(System.Drawing.Brushes.Black, cursor, 0, barwidth, height);
}
// note that we never need to draw the space, since we
// initialized the graphics to all white
// advance cursor beyond this pair
cursor += (barwidth + spcwidth);
}
}
}
return myimg;
}
}
}
In public static Image MakeBarcodeImage(string InputData, int BarWeight, bool AddQuietZone) Function
you can pass the barcodestring ,barcode weight and pass AddQuietZone as true.
Rahul S Chavhan
Pune
|
|
|
|
|
First, OP refers to having used "some barcode fonts". So he doesn't need a complete barcode generator.
Then, when posting code, please wrap it in tags like these:
<pre lang="c#">YourCodeHere();</pre>
That makes code much more readable, which is important, especially in an extend like what's given here.
How about making an article of that? It could be interesting for many.
Ciao,
luker
|
|
|
|
|
You should post links to this code, and, if you are not the author, credit the author. The code came from: [^], and/or: [^].
“But I don't want to go among mad people,” Alice remarked.
“Oh, you can't help that,” said the Cat: “we're all mad here. I'm mad. You're mad.”
“How do you know I'm mad?” said Alice.
“You must be," said the Cat, or you wouldn't have come here.” Lewis Carroll
modified 6-Feb-14 3:32am.
|
|
|
|
|
Both your links point to the same source.
But that hardly justifies univoting.
Ciao,
luker
|
|
|
|
|
I have edited my post to include a correct reference to the (possibly) second file used.
The code may have also come from here: [^].
That's really great that your psychic powers tell you who the people are that down-voted
“But I don't want to go among mad people,” Alice remarked.
“Oh, you can't help that,” said the Cat: “we're all mad here. I'm mad. You're mad.”
“How do you know I'm mad?” said Alice.
“You must be," said the Cat, or you wouldn't have come here.” Lewis Carroll
|
|
|
|
|
What's wrong with the responses you got two days ago[^]?
Ciao,
luker
|
|
|
|
|
I am unable to get the expected output and i want to try only with c# code
|
|
|
|
|
Then comment on an answer and tell the person that was trying to help you, where you have problems with putting his/her proposal into action.
"It does not work" is not the sort of comment that will help anyone.
Tell what you have and what you need instead.
Tell what's happening and what you're expecting instead.
And as far as I saw it, that's all C#.
Ciao,
luker
|
|
|
|
|
Hey Guys,
I have my SQL Server Database on machineX i name that as "OtherMachine"
I have installed my visual Studio on current machine i name that as "MyMachine".
I created windows forms on MyMachine and try to connect with Database on "OtherMachine"
View-->Server Explorer-->Add Connection-->Choose Microsoft SQL Server
In Add Connection window:
when i give Server name as
Scenario1:
OtherMachine\SQLEXPRESS
i could not find any database in the dropdown list. i get an error (Provider: SQL Network Interfaces, error:26 - Error Locating Server/Instance Specified)
But the Database are present in "OtherMachine"
Scenario2:
MyMachine\SQLEXPRESS (connecting to local database on MYMachine)
in dropdown list i get the datbase listed. its successfull.
Issue: am not able to connect to database on "OtherMachine".
Please assist.
|
|
|
|
|
|
I have a machine with SQL 2008 R2 Express Edition installed, and i have created a Database in that machine.
I cannot start "SQL Server Agent" - getting Remote Procedure Call Failed Error.
But other 2 are in running state (SQL Server (SQLEXPRESS) & SQL Server Browser)
Is that i cannot connect to this Database using the SQL 2008 R2 Express edition ????
Do i need to have SQL Server 2008 R2 installed ??
Please assist.
|
|
|
|
|
You cannot start the SQL Agent service because SQL Express doesn't include that component.
For the connection problems, did you read the blog post I linked to? Which steps from that post have you tried?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
You may also want to make sure that port 1433 is open if there is a firewall in the mix.
Thanks
JD
http://www.seitmc.com/seitmcWP
|
|
|
|
|
try
{
string s = "INSERT INTO [Students Records] (Name,Age,Class,Gender,Guardian's Name,Contact.No,Address,Email-Address) VALUES(@Name,@Age,@Class,@Gender,@Guardian's Name,@Contact.No,@Address,@Email-Address)";
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(s,con);
cmd.Connection = con;
cmd.Parameters.AddWithValue("@Name", textBox1.Text);
cmd.Parameters.AddWithValue("@Age", textBox2.Text);
cmd.Parameters.AddWithValue("@Class", textBox3.Text);
cmd.Parameters.AddWithValue("@Gender", textBox4.Text);
cmd.Parameters.AddWithValue("@Guardian's Name", textBox5.Text);
cmd.Parameters.AddWithValue("@Contact.No", textBox6.Text);
cmd.Parameters.AddWithValue("@Address", textBox7.Text);
cmd.Parameters.AddWithValue("@Email-Address", textBox8.Text);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Saved!");
}
My query can't executed successfully please help ??
|
|
|
|
|
You can't have the "'" in Guardian's Name. What database are you using?
|
|
|
|
|
Member 10564850 wrote: My query can't executed successfully please help ??
As Griff mentioned on Saturday:
Just remember in future - the better the info you give us, the quicker we can give you a solution!
Once again, you've posted your code, but not the error message, which leaves us to play another game of "guess the error".
Assuming the problem is with the column names containing special characters, the quick fix is to wrap the affected column names in square brackets. You'll also need to fix the parameter names:
string s = "INSERT INTO [Students Records] (Name, Age, Class, Gender, [Guardian's Name], [Contact.No], Address, [Email-Address]) VALUES(@Name, @Age, @Class, @Gender, @GuardiansName, @ContactNo, @Address, @EmailAddress)";
A better solution is to change your database structure so that the table and column names do not contain anything other than letters and numbers - no spaces, no punctuation, and no extended characters.
The same restrictions apply to parameter names.
If that doesn't solve the problem, then you'll need to provide the details of the exception being thrown when you try to execute the query.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Whoops! Already moved. Sorry!
|
|
|
|
|
Answered here[^].
..and now you know "why" it is not done.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
|
Again, you're putting spaces and special characters in the parameter names.
DO NOT USE SPACES AND SPECIAL CHARACTERS IN TABLE NAMES, FIELD NAMES AND PARAMETER NAMES!
Your field names should be something like this:
Name, Age, Class, Gender, GuardianName, ContactPhone, Address, EmailAddress
By making the code more "eyeball friendly" to read, you are giving yourself headaches debugging the resulting code. "Eyeball friendly" is NOT "compiler friendly"!
|
|
|
|
|
Clean-up crew needed, grammar spill... - Nagy Vilmos
|
|
|
|
|
Hi,
I am using MySQL database in my C# .NET application and saving all dates in the database as UTC_TIMESTAMP
I want to know to display it for the user in his own local time according to his Microsoft Windows?
Thanks,
Jassim
Technology News @ www.JassimRahma.com
|
|
|
|
|
Try reading the documentation on the DateTime structure, here[^].
Dim databaseUtcTime = dateTimeFromDatabase
databaseUtcTime = databaseUtcTime.SpecifyKind(DateTimeKind.Utc)
Debug.WriteLine(String.Format("UtcTime: {0}", databaseUtcTime.ToString()))
Debug.WriteLine(String.Format("LocalTime: {0}", databaseUtcTime.ToLocalTime().ToString()))
|
|
|
|
|
Alright, this is not exactly a programming question, but I also doubt that it would fit into the Lounge.
Situation: I am currently implementing the Syslog Protocol in .Net, starting with the Base classes (Message, Header, Struct. Data). The Header contains a timestamp which's formatting is exactly defined.
A timestamp may look as follows:
2014-2-4T14:22:56.235Z+1
2014-2-4T14:22:56.235Z-1.5
2014-2-4T14:22:56.235123Z+1
What I have done so far is that I consider System.DateTime being unuseable as timestamp, even with a wrapper around it it would be highly difficult since setting a single field (e.g. Day, Year, Month and so on) is only possible by parsing an entire time string, or adding a Time span.
Now to avoid these circumstances, I have implemented the following class SyslogTimestamp:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Springlog.Com.Messaging
{
public class SyslogTimestamp
{
#region Properties
static short GetDayMaxDaysOfMonth(int month, int year)
{
if (month != 2)
{
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
{
return 31;
}
else
{
return 30;
}
}
else
{
if (IsLeapYear(year))
{
return 29;
}
return 28;
}
}
private static bool IsLeapYear(int year)
{
if (year % 4 == 0)
{
if (year % 100 == 0)
{
if (year % 400 == 0)
{
return true;
}
return false;
}
return true;
}
return false;
}
int year;
public int Year
{
get { return year; }
}
int month;
public int Month
{
get { return month; }
}
int dayOfMonth;
public int DayOfMonth
{
get { return dayOfMonth; }
}
int hours;
public int Hours
{
get { return hours; }
}
int minutes;
public int Minutes
{
get { return minutes; }
}
int seconds;
public int Seconds
{
get { return seconds; }
}
int miliseconds;
public int Miliseconds
{
get { return miliseconds; }
}
double utcOffset;
public double UtcOffset
{
get { return utcOffset; }
set { utcOffset = value; }
}
#endregion
public SyslogTimestamp()
{
Reset();
}
public SyslogTimestamp(string timestamp)
{
Reset();
FromString(timestamp);
}
public SyslogTimestamp(DateTime timestamp)
{
Reset();
FromDateTime(timestamp);
}
private void Reset()
{
miliseconds = 0;
seconds = 0;
minutes = 0;
hours = 0;
dayOfMonth = 0;
month = 1;
year = 1;
utcOffset = 0;
}
public bool FromString(string dateTime)
{
Regex splitRegex = new Regex("([0-9]{4})-([1-9]|[1][0-2])-([0-2]?[0-9]|[3][0-1])[T]([0-1]?[0-9]|[2][0-3])[:]([0-5]?[0-9])[:]([0-5]?[0-9])?.?([0-9]{1,6})[Z]([+-][0-9]|[+-]?[0][1][0-2])", RegexOptions.IgnoreCase);
Match timestamp = splitRegex.Match(dateTime);
if (timestamp.Groups.Count == 9)
{
AddYears(Int32.Parse(timestamp.Groups[1].Value));
AddMonths(Int32.Parse(timestamp.Groups[2].Value));
AddDays(Int32.Parse(timestamp.Groups[3].Value));
AddHours(Int32.Parse(timestamp.Groups[4].Value));
AddMinutes(Int32.Parse(timestamp.Groups[5].Value));
AddSeconds(Int32.Parse(timestamp.Groups[6].Value));
AddMilliseconds(Int32.Parse(timestamp.Groups[7].Value));
utcOffset = Int32.Parse(timestamp.Groups[8].Value);
return true;
}
else
{
return false;
}
}
public string ToFormattedString()
{
string timezonPreSign = "+";
if (utcOffset < 0)
{
timezonPreSign = "";
}
return string.Format("{0}-{1}-{2}T{3}:{4}:{5}.{6}Z{7}{8}", year, month, dayOfMonth, hours, minutes, seconds, miliseconds, timezonPreSign, utcOffset);
}
public override string ToString()
{
return this.ToFormattedString();
}
public void FromDateTime(DateTime timestamp, bool convertToUtc = true)
{
TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(timestamp);
if (convertToUtc)
{
timestamp.Add(utcOffset);
this.utcOffset = 0;
}
else
{
this.utcOffset = utcOffset.Hours + (utcOffset.Minutes / 100);
}
AddMilliseconds(timestamp.Millisecond);
AddSeconds(timestamp.Second);
AddMinutes(timestamp.Minute);
AddHours(timestamp.Hour);
AddDays(timestamp.Day);
AddMonths(timestamp.Month);
AddYears(timestamp.Year);
}
public void Add(TimeSpan timeSpan)
{
AddMilliseconds(timeSpan.Milliseconds);
AddSeconds(timeSpan.Seconds);
AddMinutes(timeSpan.Minutes);
AddHours(timeSpan.Hours);
AddDays(timeSpan.Days);
}
public void AddMilliseconds(int val)
{
if (val + miliseconds >= 1000)
{
AddSeconds( val / 1000);
miliseconds = (val % 1000);
}
else
{
miliseconds += val;
}
}
private void AddSeconds(int val)
{
if (seconds + val >= 60)
{
AddMinutes(val / 60);
seconds = (val % 60);
}
else
{
seconds += val;
}
}
private void AddMinutes(int val)
{
if (minutes + val >= 60)
{
AddMinutes(val / 60);
minutes = (val % 60);
}
else
{
minutes += val;
}
}
private void AddHours(int val)
{
if (minutes + val >= 24)
{
AddDays (val / 24);
minutes = (val % 24);
}
else
{
minutes += val;
}
}
private void AddDays(int val)
{
short dayCount = GetDayMaxDaysOfMonth(month, year);
if (dayOfMonth + val > dayCount)
{
AddMonths(val / dayCount);
dayOfMonth = (val % dayCount);
}
else
{
dayOfMonth += val;
}
}
private void AddMonths(int val)
{
if (month + val > 12)
{
AddYears(val / 12);
month = (val % 12);
}
else
{
month += val;
}
}
private void AddYears(int val)
{
year += val;
}
public override bool Equals(object o)
{
if (o is SyslogTimestamp)
{
return DoMatch((SyslogTimestamp)o, this);
}
else
{
return false;
}
}
public static bool DoMatch(SyslogTimestamp a, SyslogTimestamp b)
{
bool doMatch = (a.year == b.Year)
&& (a.month == b.Month)
&& (a.dayOfMonth == b.DayOfMonth)
&& (a.hours == b.Hours)
&& (a.minutes == b.Minutes)
&& (a.seconds == b.Seconds)
&& (a.miliseconds == b.Miliseconds)
&& (a.utcOffset == b.UtcOffset);
return doMatch;
}
public static bool operator ==(SyslogTimestamp a, SyslogTimestamp b)
{
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
if (((object)a == null) || ((object)b == null))
{
return false;
}
return DoMatch(a, b);
}
public static bool operator !=(SyslogTimestamp a, SyslogTimestamp b)
{
return !(a == b);
}
public static bool operator <(SyslogTimestamp a, SyslogTimestamp b)
{
if (a.Year < b.Year) { return true; }
if (a.Year > b.Year) { return false; }
if (a.Month < b.Month) { return true; }
if (a.Month > b.Month) { return false; }
if (a.DayOfMonth < b.DayOfMonth) { return true; }
if (a.DayOfMonth > b.DayOfMonth) { return false; }
if ((a.Hours + a.UtcOffset) < (b.Hours + b.UtcOffset)) { return true; }
if ((a.Hours + a.UtcOffset) > (b.Hours + b.UtcOffset)) { return false; }
if (a.Minutes < b.Minutes) { return true; }
if (a.Minutes > b.Minutes) { return false; }
if (a.Seconds < b.Seconds) { return true; }
if (a.Seconds > b.Seconds) { return false; }
if (a.Miliseconds < b.Miliseconds) { return true; }
if (a.Miliseconds > b.Miliseconds) { return false; }
return false;
}
public static bool operator >(SyslogTimestamp a, SyslogTimestamp b)
{
if (a.Year > b.Year) { return true; }
if (a.Year < b.Year) { return false; }
if (a.Month > b.Month) { return true; }
if (a.Month < b.Month) { return false; }
if (a.DayOfMonth > b.DayOfMonth) { return true; }
if (a.DayOfMonth < b.DayOfMonth) { return false; }
if ((a.Hours + a.UtcOffset) > (b.Hours + b.UtcOffset)) { return true; }
if ((a.Hours + a.UtcOffset) < (b.Hours + b.UtcOffset)) { return false; }
if (a.Minutes > b.Minutes) { return true; }
if (a.Minutes < b.Minutes) { return false; }
if (a.Seconds > b.Seconds) { return true; }
if (a.Seconds < b.Seconds) { return false; }
if (a.Miliseconds > b.Miliseconds) { return true; }
if (a.Miliseconds < b.Miliseconds) { return false; }
return false;
}
public static bool operator >=(SyslogTimestamp a, SyslogTimestamp b)
{
return (a > b) || DoMatch(a, b);
}
public static bool operator <=(SyslogTimestamp a, SyslogTimestamp b)
{
return (a < b) || DoMatch(a, b);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
Of course I have Unit Tests to check the integrity of the data handling within that class:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Springlog.Com.Messaging;
namespace Springlog.Com.Messaging.UnitTests
{
[TestClass]
public class SyslogTimestampUnitTest
{
[TestMethod]
public void SyslogTimestampComparisonIntegrity()
{
SyslogTimestamp timestamp1 = new SyslogTimestamp();
SyslogTimestamp timestamp2 = new SyslogTimestamp();
SyslogTimestamp timestamp3 = new SyslogTimestamp();
SyslogTimestamp timestamp4 = new SyslogTimestamp();
timestamp1.FromDateTime(DateTime.Now);
timestamp2.FromDateTime(DateTime.Now.AddDays(-1));
timestamp3 = timestamp1;
timestamp4.FromDateTime(DateTime.Now.AddMinutes(2));
Assert.AreEqual(true, (timestamp1 > timestamp2));
Assert.AreEqual(true, (timestamp4 > timestamp1));
Assert.AreEqual(false, (timestamp1 < timestamp2));
Assert.AreEqual(true, (timestamp1 >= timestamp2));
Assert.AreEqual(false, (timestamp1 <= timestamp2));
Assert.AreEqual(true, (timestamp1 == timestamp3));
Assert.AreEqual(false, (timestamp1 != timestamp3));
Assert.AreEqual(false, (timestamp1 == timestamp4));
Assert.AreEqual(false, (timestamp1 == timestamp2));
}
[TestMethod]
public void SyslogTimestampStringConversionIntegrity()
{
DateTime now = DateTime.Now;
SyslogTimestamp timestamp = new SyslogTimestamp();
SyslogTimestamp timestamp2 = new SyslogTimestamp();
timestamp.FromDateTime(now);
timestamp.UtcOffset = 1;
Assert.AreEqual(true, timestamp2.FromString(timestamp.ToFormattedString()));
Assert.AreEqual(true, (timestamp2 == timestamp));
}
}
}
Now my question is: Can I achieve the same with System.DateTime?
I seriously doubt that, since System.DateTime's ParseExact method tends to have problems dealing with a variable amount of microseconds, and does not provide any field to store the UTC Offset.
Edit: I provided the new class implementation, since I have added various improvements.
Clean-up crew needed, grammar spill... - Nagy Vilmos
modified 5-Feb-14 8:52am.
|
|
|
|
|