How smart is SmartDate?

How smart is SmartDate?

Old forum URL: forums.lhotka.net/forums/t/2265.aspx


bgilbert posted on Friday, February 02, 2007

I have a date field that need to be represented in a UI as time only. In the Property Get, I use the SmartDate's FormatString to do the translation. This works great.

In the Property Set I do _myTime.Text=Value. Because the value parameter is a string, it sets _myTime.Date to just a time value. I was hoping it would append the time value to a min date. If I'm using a native Date type, it will do this. Am I missing something here?

RockfordLhotka replied on Friday, February 02, 2007

Can you illustrate what you mean in a couple lines of code? I'm not sure what you are saying exactly, but if SmartDate is inconsistent with DateTime I'd like to correct it.

bgilbert replied on Monday, February 05, 2007

Rocky,

This is how I've defined a time-only property:

    Public Property TimeStart() As String        <System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
        Get
            CanReadProperty(True)
            Return SmartDate.DateToString(_timeStart.Date, "h:mm tt")
        End Get <System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
        Set(ByVal value As String)
            CanWriteProperty(True)
            If Not _timeStart.Equals(value) Then               
                _timeStart.Text = value
                PropertyHasChanged()
            End If
        End Set
    End Property

After setting a new value to _timeStart, it is stored in SmartDate as the time value only. I've also tried using the FormatString property of SmartDate, but with the same result.

Barry

RockfordLhotka replied on Monday, February 05, 2007

How do you know that it is stored only as a time value?

 

Try this code:

 

    Dim sdate As Csla.SmartDate

    sdate.Text = "1:00"

    Console.WriteLine(sdate.ToString("d"))

    Console.WriteLine(sdate.ToString("h:mm tt"))

    Console.WriteLine(sdate.Date)

 

You’ll find that the console output is:

 

1/1/0001

1:00 AM

1/1/0001 1:00:00 AM

 

Which clearly shows that the SmartDate value contains both date and time parts, and that the date part is 1/1/0001.

 

If you try the same thing with a DateTime:

 

    Dim dtime As DateTime

    dtime = CDate("1:00")

    Console.WriteLine(dtime)

 

You’ll get the same result as SmartDate, so there is parity.

 

Rocky

 

 

 

From: bgilbert [mailto:cslanet@lhotka.net]
Sent: Monday, February 05, 2007 8:08 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] How smart is SmartDate?

 

Rocky,

This is how I've defined a time-only property:

    Public Property TimeStart() As String        <System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
        Get
            CanReadProperty(True)
            Return SmartDate.DateToString(_timeStart.Date, "h:mm tt")
        End Get <System.Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
        Set(ByVal value As String)
            CanWriteProperty(True)
            If Not _timeStart.Equals(value) Then   ;             
                _timeStart.Text = value
                PropertyHasChanged()
            End If
        End Set
    End Property

After setting a new value to _timeStart, it is stored in SmartDate as the time value only. I've also tried using the FormatString property of SmartDate, but with the same result.

Barry


bgilbert replied on Monday, February 05, 2007

The difference in my code is that my property set receives the tt portion of the string from the UI. When I set "01:00 AM", the Date property and the DBValue property both return #01:00:00#. SQL Server cannot handle this value in a Date column. When you do the same with a native Date variable, it appends a date and returns "01/01/0001 01:00:00 AM", which SQL Server likes.

Barry

RockfordLhotka replied on Monday, February 05, 2007

I am afraid I still don’t understand.

 

Put this code in a console app:

 

    Dim sdate As Csla.SmartDate

 

    sdate.Text = "01:00 AM"

    Console.WriteLine(sdate.ToString("d"))

    Console.WriteLine(sdate.ToString("hh:mm tt"))

    Console.WriteLine(sdate.Date)

    Console.WriteLine(sdate.DBValue)

    Console.Read()

 

Then you get this output:

 

1/1/0001

01:00 AM

1/1/0001 1:00:00 AM

1/1/0001 1:00:00 AM

 

Obviously the Date and DBValue properties are returning exactly what you’d expect. And exactly what you’d get back if you did this same thing with a normal Date or DateTime field.

 

Rocky

bgilbert replied on Monday, February 05, 2007

Well, now I'm confused. Your code works for me. However, in my code (see above), the Date and DBValue properties still only return the time portion. Here are the results I get:

_timeStart.Date returns #01:00:00 AM#
_timeStart.DBValue returns #01:00:00 AM#
_timeStart.Date.ToString returns "1/1/0001 01:00:00 AM"
_timeStart.DBValue.ToString returns "1/1/0001 01:00:00 AM"
_timeStart.ToString returns "1/1/0001"

If I try to pass DBValue to a parameter in my Update, it throws an overflow exception.

I don't see what can be going wrong, but I'll keep poking at it.

Barry

bgilbert replied on Monday, February 05, 2007

More information:

When I evaluate the property values using Console.WriteLine, it returns the expected value. However, when I check the same values in the immediate window, I get the wrong values. I've never seen a difference between Console.WriteLine and Immediate window calls. The botton line is that using DBValue as a parameter makes SQL Sever choke (SqlDateTime Overflow exception).

Barry

RockfordLhotka replied on Monday, February 05, 2007

Can you confirm that DateTime works?

Dim x As DateTime = CDate("01:00 AM")
cm.Parameters.Add("@thedate", x)

or whatever is comparable to what you are doing?

I think the issue may be that 1/1/0001 isn't a valid date for SQL Server. In other words, the minimum value for a .NET date may be smaller than the minimum date for SQL Server. (though I could be wrong)

bgilbert replied on Monday, February 05, 2007

You're right. This fails the same way with CDate("01:00 AM").

In SQL Server, the date range for DateTime is January 1, 1753, through December 31, 9999
For SmallDateTime, it's January 1, 1900, through June 6, 2079.

1/1/0001 won't work in either case.

I'll add the minimum date to my time value in the property set.

Sorry to take up your time.

Thanks for the help,
Barry

JoeFallon1 replied on Monday, February 05, 2007

I use the DateRequired validation rule to ensure that the range of the date fits SQL Server.
It is part of my module of common rules, so it is Shared.

'==================================================================

 'Rule ensuring a Date value is present and within the smalldatetime range allowed by SQL Server.
    'Blank values are not allowed.
    Public Function DateRequired(ByVal target As Object, ByVal e As RuleArgs) As Boolean
      Dim ruleArg As MyRuleArgs = DirectCast(e, MyRuleArgs)
      Dim propertyName As String = ruleArg.PropertyName
      Dim propertyDescription As String = ruleArg.PropertyDescr

      'The property Get is called on a field like MyDate and then a String value is returned.
      'It could be Empty so do not simply cast to CDate. Test if it IsDate first.
      Dim value As Object = CallByName(target, propertyName, CallType.Get)

      If IsDate(value) Then
        If value < #1/1/1900# OrElse value > #6/6/2079 11:59:00 PM# Then
          e.Description = GetDescription(target, propertyName, propertyDescription) & " is out of the allowed range. Must be between 1/1/1900 and 6/6/2079."
          Return False
        Else
          Return True
        End If
      Else
        e.Description = GetDescription(target, propertyName, propertyDescription) & " is not a date value."
        Return False
      End If
    End Function

'==================================================================

Joe

 

Copyright (c) Marimer LLC