Taking a DateTime value and only accepting time and vice versa - c#

I'm currently developing an application to function as a todo - list and i was wondering how do i accept a Value from a date time box, but only use the value of the date, or the value of the time. I'm currently doing it like this.
DateTime ted = appointmentDateTimeDate.Value; //The date
DateTime at = appointmentDateTimeTime.Value; //The time
should i be doing this another way?

Use DateTime.Date property for date, and DateTime.TimeOfDay for time:
DateTime ted = appointmentDateTimeDate.Date; //The date
TimeSpan at = appointmentDateTimeTime.TimeOfDay; //The time

The BCL doesn't really separate dates and times nicely.
If you're happy to take a new external dependency, I'd like to plug my Noda Time library, which will let you separate things out clearly into LocalDate and LocalTime. To perform the conversion from a date/time picker you'd probably use:
var dateAndTime = LocalDateTime.FromDateTime(appointmentDateTimeDate.Value);
LocalDate date = dateAndTime.LocalDate;
LocalTime time = dateAndTime.LocalTime;

Like others pointed out a DateTime always has both a date and a time component. So although it's possible to save both independently using two DateTime, in most cases it's recommendable to save both together in a single DateTime instance.
You should see if you really need both values separated or if your application could combine both in one property, which will make things easier.

A DateTime value ALWAYS contains both the date and the time, whether you use both or not.
You can use the .Date property of a DateTime to get "just the date". it will still have a time value, but the time value will be midnight. You can also use the .TimeOfDay property to get the time portion, which will be a TimeSpan indicating the number of ticks since midnight.
I'm taking a leap here and assuming you're trying to set the date with one control an d the time with another in the UI. Here's a sample of some code we use to do this using an Ajax CalendarExtender attached to a textbox and a custom TimePicker control.
DateTime dt;
try
{
dt = Convert.ToDateTime(txtViewDate.Text).AddHours(txtViewTime.Hour).AddMinutes(txtViewTime.Minute);
if (txtViewTime.AmPm == MKB.TimePicker.TimeSelector.AmPmSpec.PM)
{
dt = dt.AddHours(12);
}
System.Diagnostics.Debug.WriteLine(dt.ToString());
}
catch (Exception)
{
// abort processing
return;
}

Related

Change format of DateTime without converting to string

I'm new in c# and I have Datetime variable like:
DateTime startingDate
value = 8/8/2018 4:16:18 PM
I want value like 8/8/2018, how can I just drop hours minutes seconds and PMvalue without converting to string? because I'm forced DateTime type for another thing.
In C# (as in many other languages) there is no separate Date and Time, it's just DateTime. Regardless of that though, there are many use cases where you only need a date. In C# it's assumed that if you just need 8/8/2018 then in reality you are working with 8/8/2018 0:00:00.000.
If you need to work with just the Date but still keep it as a DateTime, then the most straightfoward method is to use .Date (i.e. startingDate.Date). This can get a little confusing since the default .ToString() for DateTime represents it (in whatever is the cultural norm for your computer) as Month/Day/Year Hour:Minute:Second AM/PM.
Also, for further clarification, DateTime is an object that has a variety of different properties (Year, Month, Day, Hour, Minute, Second etc), so thinking of it having a "format" is incorrect. It's a collection of things that together make up a Date and/or Time.

Correct way to convert datetime timezone for display

We are developing a website and currently, the timezone of the website and database is in German time zone (European standard time zone). But the application is being accessed from the US also. There is a screen in the application which contains a DateTime field called ValidFrom and the time we are storing is UTC time. currently, users are not selecting the time so we are using .NET built-in DateTime.UTCNow to store DateTime value in the database. But the problem is while displaying, we need to display it according to User timezone. So after googling for many hours, we found two solutions one using moment and another approach is using DateTime.SpecifyKind. We tried using moment.js but it converted the date time to local time once again. So we ended up using DateTime.SpecifyKind as below.
[DataMember]
private DateTime _validFrom;
public DateTime ValidFrom
{
get { return _validFrom; }
set { _validFrom = DateTime.SpecifyKind(value, DateTimeKind.Utc); }
}
And now the values are displayed according to timezone. But my doubt is, is it the correct approach to handle timezone display or any other better solution exist?
I'd use DateTimeOffset instead, something like:
var utc = DateTimeOffset.UtcNow;
var tz = TimeZoneInfo.FindSystemTimeZoneById("Your Specific Time Zone Id");
var zonedDateTime = TimeZoneInfo.ConvertTime(utc, tz);
Save the UTC and user's time zone in the database, and convert UTC to specific time zone any time you want to show it to your users. I also suggest you take a look at NodaTime if you want to do anything serious with date and time. The built-in DateTime in .Net is misleading.
I wrote an extension method for this:
public static DateTime ConvertFromUTC(this DateTime date, TimeZoneInfo destZone)
{
var utcZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
return TimeZoneInfo.ConvertTime(date, utcZone, destZone);
}
However, if you plan to use something like this you need to be aware of daylight saving time. The result may be off if the conversion crosses a DST change in either timezone. So it isn't really suitable if you need absolute precision, which depends on the website, e.g.: is it a blog or a stock trading app?

How to differentiate between DateTime, Date and Time

There are three styles of Date and Time that can go into a DateTime variable; DateTime, Date or Time. I would like to differentiate between them. How can I do so?
I am creating column filtering on a DataGrid. Depending if it is one of the three the filter will display a DateTime picker or a DatePicker or a Time picker.
This classification is not part of the struct. IOW there's no built-in way to do this, so it's up to you to pick the implementation you'd like.
It has been suggested to check if the TotalSeconds == 0, which may satisfy you, imo it's a wonderful solution, but I think it should be used with caution because it is limited. Because what if you want to have a time+date that points to the date when TotalSeconds that really is == 0. This approach will turn this into just a date automatically.
I suggest that if you do not associate this time with a date, choose TimeSpan and make your life so much easier. However I assume this is not the case.
So, if the time really is associated with a date, I suggest you simply make your own type that wraps a DateTime, plus a boolean flag that will answer your question: is it just a date or date+time?.
This is obvious but I simply must say this anyways: if you do take this approach - encapsulate & hide!
If you expose DateTime as a field, an end-user might change the time of a date, expecting it to become date+time, yet the flag will not follow along. So don't just make a wrapper, make your own type that just uses DateTime internally.
There is no absolute way to differentiate. A DateTime always has a date portion and a time portion. If you create a DateTime from just a date then the time portion will be zeroed to midnight, but there is no difference between that and a value that actually represents the stroke of midnight on that date. If you create a DateTime from just a time then the date portion will be equal to #1/01/0001#, but there's no difference between that and a value that actually represents a time on the first day of the new era.
One option is to assume that a DateTime with a non-zero time and a date of #1/01/0001# represents just a time and a value with a zeroed time portion represents just a date. With that in mind, you could add this extension:
public enum DateTimeType
{
Date,
Time,
DateAndTime
}
public static class DateTimeExtensions
{
private static readonly DateTime ZeroDate = new DateTime(1, 1, 1);
public static DateTimeType GetDateTimeType(this DateTime value)
{
if (value.TimeOfDay == TimeSpan.Zero)
{
return DateTimeType.Date;
}
if (value.Date == ZeroDate)
{
return DateTimeType.Time;
}
return DateTimeType.DateAndTime;
}
}
The only way to check if DateTime has a date value is to make it a nullable type.
So something like this:
DateTime? dt;
if(dt.HasValue) {
//has date
if(dt.Value.TimeOfDay.TotalSeconds == 0) {
// display datepicker
} else {
// display timepicker
}
} else {
// show date time picker
}
Other than that, a regular DateTime will always have a date value (if not time value, or both). That is because it's a struct, hence it is not nullable unless you "make" it so (by wrapping in Nullable, which is done either manually (Nullable<DateTime>) or much simpler - by appending ? to the type (DateTime?) as demonstrated above).
If you have an option to go with different datatype (other than DateTime), then I suggest looking at NodaTime (Microsoft should simply build this into CLR and drop their lame DateTime struct).
You can then have 3 nullable properties
LocalDate? Date;
LocalDateTime? DateTime;
LocalTime? Time;
So based on which prop has value, you show the appropriate control. Of course, you also need to set the appropriate property which I'm not sure if you have any control on.

Create a date time with month and day only, no year

I am creating a timer job in VS for sharepoint, and I want to create a Date object that only has a month and day. The reason for this is because I want this job to run annually on the specific date.
If it's not possible with a date object, then how would you go about doing this?
Here's what I've got:
DateTime value = new DateTime(2010, 1, 18);
Well, you can create your own type - but a DateTime always has a full date and time. You can't even have "just a date" using DateTime - the closest you can come is to have a DateTime at midnight.
You could always ignore the year though - or take the current year:
// Consider whether you want DateTime.UtcNow.Year instead
DateTime value = new DateTime(DateTime.Now.Year, month, day);
To create your own type, you could always just embed a DateTime within a struct, and proxy on calls like AddDays etc:
public struct MonthDay : IEquatable<MonthDay>
{
private readonly DateTime dateTime;
public MonthDay(int month, int day)
{
dateTime = new DateTime(2000, month, day);
}
public MonthDay AddDays(int days)
{
DateTime added = dateTime.AddDays(days);
return new MonthDay(added.Month, added.Day);
}
// TODO: Implement interfaces, equality etc
}
Note that the year you choose affects the behaviour of the type - should Feb 29th be a valid month/day value or not? It depends on the year...
Personally I don't think I would create a type for this - instead I'd have a method to return "the next time the program should be run".
How about creating a timer with the next date?
In your timer callback you create the timer for the following year? DateTime has always a year value. What you want to express is a recurring time specification. This is another type which you would need to create.
DateTime is always represents a specific date and time but not a recurring date.
There is no such thing like a DateTime without a year!
From what I gather your design is a bit strange:
I would recommend storing a "start" (DateTime including year for the FIRST occurence) and a value which designates how to calculate the next event... this could be for example a TimeSpan or some custom structure esp. since "every year" can mean that the event occurs on a specific date and would not automatically be the same as saysing that it occurs in +365 days.
After the event occurs you calculate the next and store that etc.
Anyway you need 'Year'.
In some engineering fields, you have fixed day and month and year can be variable. But that day and month are important for beginning calculation without considering which year you are. Your user, for example, only should select a day and a month and providing year is up to you.
You can create a custom combobox using this: Customizable ComboBox Drop-Down.
1- In VS create a user control.
2- See the code in the link above for impelemnting that control.
3- Create another user control and place in it 31 button or label and above them place a label to show months.
4- Place the control in step 3 in your custom combobox.
5- Place the control in setp 4 in step 1.
You now have a control with only days and months. You can use any year that you have in your database or ....

Function to return only date

I have made a function to convert a textbox value to date.
I want to store the converted date in a datetime field in my business object with only date and not time like in format(yyyy-MM-dd)
My function is returning date along with time
public static DateTime ExtractDate(string myDate)
{
DateTime result = DateTime.MinValue;
if (myDate != null)
{
try
{
result=DateTime.Parse(myDate, new System.Globalization.CultureInfo("en-CA", true), System.Globalization.DateTimeStyles.AdjustToUniversal).ToString("yyyy-MM-dd");
}
catch (Exception)
{
throw new ApplicationException("DateTime conversion error");
}
}
return (result.Date);
}
DateTime itself always includes a time, in the case when you're setting it equal to a 'date' then the time will be 00:00:00. When it comes to displaying the string you'll need to use a format string that includes just the date part.
Just use:
result = DateTime.Parse(...).Date;
Therre's no need to convert the date/time back to a string first. The resulting DateTime will just be midnight on the relevant date.
I see that you're adjusting to universal time - you need to be aware that that may change the date. Dates are inherently local - i.e. my August 25th may well start at a different time to yours due to time zones. Alternatively, you could parse it as if it were in UTC to start with and treat it that way. You just need to be careful with what you're doing - you could run into problems where midnight doesn't exist on some days in some time zones. (Been there, done that...)
I would also suggest using DateTime.TryParseExact and specifying the input format. In particular, if you only expect users to enter dates, then specify appropriate date formats. Using TryParseExact instead of ParseExact means you don't have to catch an exception to notice that the user hasn't entered a valid date.
EDIT: Just to clarify: .NET doesn't have a type representing "just a date". Noda Time does, but that's not ready for production yet :( Normally you'd just use a DateTime and ignore the time part.
Date property returns a DateTime with time set to "00.00:00". You can not remove time from a DateTime, you can avoid to show it in the GUI using string.Format("d", yourDate).
I would change the method and return a string instead of a DateTime, because there is always time attached (therefor also the name DateTIME ;-))
If you return a string, you can do something like:
return DateTime-object.ToString("yyyy/MM/dd");
Good luck!

Categories

Resources