|
Introduction
I recently made the transition from Delphi to C#. I noticed that some of the datetime utilities that I used to use were not available in C#. So I recreated them. Hopefully this will save someone some time in the future.
The Codeusing System;
namespace Concepts2Code.Utilities
{
public enum Quarter
{
First = 1,
Second = 2,
Third = 3,
Fourth = 4
}
public enum Month
{
January = 1,
February = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12
}
public class DateUtilities
{
#region Quarters
public static DateTime GetStartOfQuarter( int Year, Quarter Qtr )
{
if( Qtr == Quarter.First )
return new DateTime( Year, 1, 1, 0, 0, 0, 0 );
else if( Qtr == Quarter.Second )
return new DateTime( Year, 4, 1, 0, 0, 0, 0 );
else if( Qtr == Quarter.Third )
return new DateTime( Year, 7, 1, 0, 0, 0, 0 );
else
return new DateTime( Year, 10, 1, 0, 0, 0, 0 );
}
public static DateTime GetEndOfQuarter( int Year, Quarter Qtr )
{
if( Qtr == Quarter.First )
return new DateTime( Year, 3,
DateTime.DaysInMonth( Year, 3 ), 23, 59, 59, 999 );
else if( Qtr == Quarter.Second )
return new DateTime( Year, 6,
DateTime.DaysInMonth( Year, 6 ), 23, 59, 59, 999 );
else if( Qtr == Quarter.Third )
return new DateTime( Year, 9,
DateTime.DaysInMonth( Year, 9 ), 23, 59, 59, 999 );
else
return new DateTime( Year, 12,
DateTime.DaysInMonth( Year, 12 ), 23, 59, 59, 999 );
}
public static Quarter GetQuarter( Month Month )
{
if( Month <= Month.March )
return Quarter.First;
else if( ( Month >= Month.April ) && ( Month <= Month.June ) )
return Quarter.Second;
else if( ( Month >= Month.July ) && ( Month <= Month.September ) )
return Quarter.Third;
else
return Quarter.Fourth;
}
public static DateTime GetEndOfLastQuarter()
{
if( (Month)DateTime.Now.Month <= Month.March )
return GetEndOfQuarter( DateTime.Now.Year - 1, Quarter.Fourth);
else
return GetEndOfQuarter( DateTime.Now.Year,
GetQuarter( (Month)DateTime.Now.Month));
}
public static DateTime GetStartOfLastQuarter()
{
if( (Month)DateTime.Now.Month <= Month.March )
return GetStartOfQuarter( DateTime.Now.Year - 1, Quarter.Fourth);
else
return GetStartOfQuarter( DateTime.Now.Year,
GetQuarter( (Month)DateTime.Now.Month));
}
public static DateTime GetStartOfCurrentQuarter()
{
return GetStartOfQuarter( DateTime.Now.Year,
GetQuarter( (Month)DateTime.Now.Month ));
}
public static DateTime GetEndOfCurrentQuarter()
{
return GetEndOfQuarter( DateTime.Now.Year,
GetQuarter( (Month)DateTime.Now.Month ));
}
#endregion
#region Weeks
public static DateTime GetStartOfLastWeek()
{
int DaysToSubtract = (int)DateTime.Now.DayOfWeek + 7;
DateTime dt =
DateTime.Now.Subtract(System.TimeSpan.FromDays( DaysToSubtract ) );
return new DateTime( dt.Year, dt.Month, dt.Day, 0, 0, 0, 0 );
}
public static DateTime GetEndOfLastWeek()
{
DateTime dt = GetStartOfLastWeek().AddDays(6);
return new DateTime( dt.Year, dt.Month, dt.Day, 23, 59, 59, 999 );
}
public static DateTime GetStartOfCurrentWeek()
{
int DaysToSubtract = (int)DateTime.Now.DayOfWeek ;
DateTime dt =
DateTime.Now.Subtract( System.TimeSpan.FromDays( DaysToSubtract ) );
return new DateTime( dt.Year, dt.Month, dt.Day, 0, 0, 0, 0 );
}
public static DateTime GetEndOfCurrentWeek()
{
DateTime dt = GetStartOfCurrentWeek().AddDays(6);
return new DateTime( dt.Year, dt.Month, dt.Day, 23, 59, 59, 999 );
}
#endregion
#region Months
public static DateTime GetStartOfMonth( Month Month, int Year )
{
return new DateTime( Year, (int)Month, 1, 0, 0, 0, 0 );
}
public static DateTime GetEndOfMonth( Month Month, int Year )
{
return new DateTime( Year, (int)Month,
DateTime.DaysInMonth( Year, (int)Month ), 23, 59, 59, 999 );
}
public static DateTime GetStartOfLastMonth()
{
if( DateTime.Now.Month == 1 )
return GetStartOfMonth( 12, DateTime.Now.Year - 1);
else
return GetStartOfMonth( DateTime.Now.Month -1, DateTime.Now.Year );
}
public static DateTime GetEndOfLastMonth()
{
if( DateTime.Now.Month == 1 )
return GetEndOfMonth( 12, DateTime.Now.Year - 1);
else
return GetEndOfMonth( DateTime.Now.Month -1, DateTime.Now.Year );
}
public static DateTime GetStartOfCurrentMonth()
{
return GetStartOfMonth( DateTime.Now.Month, DateTime.Now.Year );
}
public static DateTime GetEndOfCurrentMonth()
{
return GetEndOfMonth( DateTime.Now.Month, DateTime.Now.Year );
}
#endregion
#region Years
public static DateTime GetStartOfYear( int Year )
{
return new DateTime( Year, 1, 1, 0, 0, 0, 0 );
}
public static DateTime GetEndOfYear( int Year )
{
return new DateTime( Year, 12,
DateTime.DaysInMonth( Year, 12 ), 23, 59, 59, 999 );
}
public static DateTime GetStartOfLastYear()
{
return GetStartOfYear( DateTime.Now.Year - 1 );
}
public static DateTime GetEndOfLastYear()
{
return GetEndOfYear( DateTime.Now.Year - 1 );
}
public static DateTime GetStartOfCurrentYear()
{
return GetStartOfYear( DateTime.Now.Year );
}
public static DateTime GetEndOfCurrentYear()
{
return GetEndOfYear( DateTime.Now.Year );
}
#endregion
#region Days
public static DateTime GetStartOfDay( DateTime date )
{
return new DateTime( date.Year, date.Month, date.Day, 0, 0, 0, 0 );
}
public static DateTime GetEndOfDay( DateTime date )
{
return new DateTime( date.Year, date.Month,
date.Day, 23, 59, 59, 999 );
}
#endregion
}
}
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 31 (Total in Forum: 31) (Refresh) | FirstPrevNext |
|
 |
|
|
I have a problem using a DateTime under these circumstances:
We use DateTime in .net and SQL Server as a birthday field. Some people only know the year, or the year and month. So month and day can be 0 (because unknown) and not 1 or something else.
1) How can i use the DateTime .net object in this case?
return DateTime.ParseExact(date, "dd.MM.yyy", null); // not possible cause month or day can be 0
DateTime d = new DateTime(year, 0,0); // also not possible, month and day can not be 0
2) param = new SqlParameter(); param.DbType = DbType.DateTime; param.ParameterName = "@dayofBirth"; // DateTime object param.Value = dayofBirth;
if (param.Value == null) param.Value = DBNull.Value;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The datetime class does not really allow for the month, day, or year to be a zero value. Therefore your only choice is to store each part of the datetime value in a seperate field in the database or use a string expression (like "MMDDYYYY") in order to represent a partial date. For example a string like "11002008" would mean november 2008 with no value for the day.
From a programming perspective you may want to create an object class similar to this to use in your application
public class PartialDateTime { public int? Day { get; set; } public int? Month { get; set; } public int? Year { get; set; } }
Using this class you could create a partial date like this:
new PartialDateTime{ Day = null, Month = 11, Year = 2008 }
If you decide to store the partial date in the database as a string pattern of MMDDYYYY you could override the ToString() method. This way when you are setting the database parameters you could easily "deserialize" the value to the database. You could also create a constructor to take the MMDDYYYY pattern which would initiliaze the Day, Month and Year values.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I recently found out from a developer at Quest that they are using my C# datetime utilities in Toad for SQL Server. It is always cool to find out where your code is being used. Especially with a premier product like TOAD!!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
I'm creating a library in C# that encrypts a set of data using a DateTime as key. The problem is:
When the TotalDays of a date is calculated in Delphi, it uses the days difference between 31/12/1899 12:00am and my date, for example 07/03/2008 13:46:22 (my date format is dd/MM/yyyy hh:mm:ss).
When I calculate this difference with C# (using the TimeSpan), it produces a difference of 0.5 days to Delphi TDateTime.
Make a test, creating a TDateTime in Delphi with the value 07/03/2008 13:46:22, and in C# do this:
DateTime startDate = new DateTime(1899,12,31,12,00,00); DateTime endDate = new DateTime(2008,03,07,13,46,22); TimeSpan difference = endDate - startDate;
Console.WriteLine(difference.TotalDays.ToString());
The formula of get fractional days of C# (TimeSpan.TotalDays) is different of Delphi formula. Do you know how can I fix this?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I can't figure out what I've done wrong!!! Quite annoying. I've got a webpage that's got a calendar control on it that's connected to a repeater that retrieves data from that month and only that month of the data. It seems to compile right and everything, but it comes up with no data when I run it in the form of the repeater. I'm assuming it's because of the date format or something. Everything to do with my computer is in dd/mm/yyyy format. Please can someone help me figure out what's wrong with this? Here's my code for my view.aspx page:
using System; using System.Data; using System.Data.SqlClient; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
public partial class View : System.Web.UI.Page { protected DataSet dsAd; protected void Page_Load(object sender, EventArgs e) { if (!User.Identity.IsAuthenticated) { Response.Redirect("Default.aspx"); }
if (!IsPostBack) { Calendar1.VisibleDate = DateTime.Today; AdsDataset(); } }
protected void AdsDataset() { DateTime firstDate = new DateTime(Calendar1.VisibleDate.Year, Calendar1.VisibleDate.Month, 1); DateTime lastDate = GetFirstDayOfNextMonth(); dsAd = GetCurrentMonthData(firstDate, lastDate); }
protected DateTime GetFirstDayOfNextMonth() { int monthNumber, yearNumber; if (Calendar1.VisibleDate.Month == 12) { monthNumber = 1; yearNumber = Calendar1.VisibleDate.Year + 1; } else { monthNumber = Calendar1.VisibleDate.Month + 1; yearNumber = Calendar1.VisibleDate.Year; } DateTime lastDate = new DateTime(yearNumber, monthNumber, 1); return lastDate; }
protected DataSet GetCurrentMonthData(DateTime firstDate, DateTime lastDate) { DataSet dsMonth = new DataSet(); ConnectionStringSettings cs; cs = ConfigurationManager.ConnectionStrings["ConnectionString1"]; String connString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; SqlConnection dbConnection = new SqlConnection(connString); String query; query = "SELECT * FROM Advertising WHERE DateAdded >= '" + firstDate + "' AND DateAdded <= '" + lastDate + "'"; SqlCommand dbCommand = new SqlCommand(query, dbConnection);
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(dbCommand); try { sqlDataAdapter.Fill(dsMonth); Repeater1.DataSource = dsMonth; Repeater1.DataBind(); } catch {
} return dsMonth; }
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e) { DateTime nextDate; if (dsAd != null) { foreach (DataRow dr in dsAd.Tables[0].Rows) { nextDate = (DateTime)dr["AD"]; if (nextDate == e.Day.Date) { e.Cell.BackColor = System.Drawing.Color.Pink; } } } } protected void Calendar1_VisibleMonthChanged(object sender, MonthChangedEventArgs e) { AdsDataset(); }
protected void Calendar1_SelectionChanged(object sender, EventArgs e) { int myMonth = Calendar1.SelectedDate.Month; } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The major problem that I see with your code resides in the GetCurrentMonthData method. You are building the sql by appending strings together instead of using parameterized sql statements. Therefore when you do this:
"SELECT * FROM Advertising WHERE DateAdded >= '" + firstDate + "' AND DateAdded <= '" + lastDate + "'";
You are forcing the firstDate variable to be casted to a string. My guess would be that the toString method for a date is probably not in the desired format. Therefore I would modify your code to use the following
SqlCommand dbCommand = new SqlCommand("SELECT * FROM Advertising WHERE DateAdded >= @firstDate AND DateAdded <= @lastDate", dbConnection);
dbCommand.Parameters.AddWithValue( "@firstDate", firstDate ); dbCommand.Parameters.AddWithValue( "@lastDate", lastDate );
By using parameters you will have a better chance of getting back the correct results. Even if this doesn't fix your problem, in general I would recommend using parameterized sql statements. It is easier to read, maintain and will save you from the trouble of worrying about escaping single quotes.
As an alernative, if you want to try to fix this without using parameterized sql statments, you could use the toString method of the datetime class and specify the date time format that you want to use. For example:
firstDate.toString( 'MM/dd/yyyy' ) or
firstDate.toString( 'dd/MM/yyyy' )
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 Thanks for the great utilities. You saved me a lot of time! I noticed that the code does not perform correctly when used with SQL Server. This is not an error in your code, but rather an anomoly with SQL Server. This query (run in query analyzer) will include records from 3/1/2006:
SELECT * FROM orders WHERE datetime BETWEEN '02/01/2006 00:00:00' AND '02/28/2006 23:59:59.999'
If you strip off the last "9", it runs as expected. I modified my copy of the code to only add 99 instead of 999 to the GetEndOfXXXX() methods.
Mike
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi, I am facing a date format problem while doing globalization.I am setting the regional setting as German. I am converting a date into the format 'dd-MMM-yyyy'(the middle tyre of my project supports only this format) using my C# code. say for example consider the date 25-03-2005. The name for the month of March in German is März. While converting to the above said format,.NET is not understading the spl character in the name of the month. So it converts March into 'Mrz'. The result of formatting is 25-Mrz-2005. But the database (either oracle or Sqlserver) can't understand 'Mrz', it can understand only 'Mär'. For the month of March, i can't do anything with my application. How to solve it? But the constraint is the date format should be dd-MMM-yyyy. Kindly help me to resolve this.
With Love Siva.
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
Some refactoring fun...
How about:
public DateTime StartOfThisQuarter(DateTime date) { return (new DateTime(date.Year, (int)Math.Ceiling(date.Month / 3D) * 3 - 2, 1)); }
public DateTime StartOfLastQuarter(DateTime date) { return (new DateTime(date.Year, (int)Math.Ceiling(date.Month / 3D) * 3 - 2, 1)).AddMonths(-3); }
public DateTime StartOfLastMonth(DateTime date) { return date.AddDays(-date.Day + 1).AddMonths(-1); }
etc. etc.
Still thinking about Start/End of Week...
|
| Sign In·View Thread·PermaLink | 4.00/5 (1 vote) |
|
|
|
 |
|
|
Seconded. I think typing the conditions, rather than using simple math is a little wasteful, given that the values will never change. Plus, it would leave you with less code.
I'd have coded methods like this:
public static Quarter GetQuarter( Month Month ) { return ((Quarter)((int)Month / 3)); }
public static DateTime GetStartOfQuarter( int Year, Quarter Qtr ) { return new DateTime(Year, (int)Qtr * 3 - 2, 1, 0, 0, 0, 0); }
(sorry, but I haven't run those through a compiler, but you get the general idea... )
Programming is life, The rest is mere details.
Omer van Kloeten
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Has anyone tried to compile this code? When I try, I receive the following error:
C:\Visual Studio Projects\aji\Utility\DateUtil.cs(61): The type or namespace name 'Quarters' could not be found (are you missing a using directive or an assembly reference?)
I wasn't quite sure what to do, but I changed all occurance of "Quarters" to "Quarter". After recompiling, I started gettting the following:
C:\Visual Studio Projects\aji\Utility\DateUtil.cs(76): No overload for method 'GetEndOfQuarter' takes '3' arguments
and
C:\Visual Studio Projects\aji\Utility\DateUtil.cs(78): The best overloaded method match for 'aji.Utility.DateUtil.GetQuarter(aji.Utility.Month)' has some invalid arguments
and
C:\Visual Studio Projects\aji\Utility\DateUtil.cs(78): Argument '1': cannot convert from 'int' to 'aji.Utility.Month'
Any help would be appreciated. Thanks to all that reply.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Can you post the code that is causing the error? I am speculating from the error messages that you are not passing the proper parameters to the methods. However, it is impossible to tell hat the errors are without seeing the code.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Michael,
Thank you for the quick reply. To address your request regarding posting code.... I haven't got anything to post. All I'm trying to do is to take the source that I downloaded from this site and compile it. The error messages are compile errors.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Try to put a using Concepts2Code.Utilities in your .cs file you use the lib from. And put a reference to the library.
Live is to short to be angered about lost chances!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks KenGuru but Michael has corrected the bugs and forwarded the corrected version to me. He will be making this version available soon on this site. Thanks again for your response.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Great little utility class. Seeing as these are all date based it would be nice to see a good set of Unit Tests associated with them just so anyone adopting these would have more comfort in knowing that they're using tested code.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi!
You maybe can simplify the whole utility by creating a "PeriodType" enumeration with members as Year, Quarter, Month, Day (and even go down to Hour, Second etc.)
Then you can make a Floor and a Ceil function that works as a StartOfPeriodType and EndOfPeriodType function. Instead of making one function for each Month, Year and Quarter, you just specify the periodtype in the function. Then I also prefer using the DateTime datatype instead of int for specifying month or quarter. The month Mars 2005 could be defined as new DateTime("2005-03-01") for example.
Example of definiation of Flooer function:
public static DateTime Floor(PeriodType p, DateTime d) { ... }
/Christian
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This works fine for a Calendar Year but what if you are using a Fiscal Calendar? A lot of business do not follow the true Calendar Year, where the beginning of the year is Jan. 1. For example the US Government Fiscal Year begins Oct. 1.
I would think that to extend this to work with a Fiscal Calendar you would need some sort of look-up table to calculate the true beginning/end of the years or quarters.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
I've been using FxCop on and off and it's shown me a few things you might be interested in.
- only enums with the [Flags] attribute should be pluralised. - classes with only static members should be marked sealed and have a private constructor. - method parameter names should start with a lowercase letter.
Also, calls to DateTime.Now can be relatively slow. In some of your methods/blocks you could call it once, then share the result.
Of course these are just guidelines 
Thanks for the code!
Drew Noakes drewnoakes.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You widely use here month of year as int. And also this is a style of .NET FCL. Frankly, I personally don't like using int for months. Why don't you define an one more enumeration with month's names? Perhaps it could complicate a code in parts where you use int month, but... could also improve a readability of code . What do you think?
Alexander Turlov Software development consultant, MCP
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
| | |