-2

I am trying to pass DateTime.MaxValue into a constructor, but for some reason when it is passed, the Ticks property changes from 315537897599999999 to 3155378975990000000, making it difficult to use for comparison.

DateTime dt = DateTime.MaxValue; //here it is 315537897599999999

OfferSetting setting = new OfferSetting(settingCode
    , (Equals(row["AccountId"], "")) ? null : row["AccountId"].ToString()
    , (Equals(row["Arguments"], "")) ? null : row["Arguments"].ToString()
    , (Equals(row["StartDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? DateTime.MinValue : Convert.ToDateTime(row["StartDate"])
    , (Equals(row["EndDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));

Once in the constructor for OfferSetting, it changes to 3155378975990000000:

public OfferSetting(SettingCode settingCode, string accountId, string arguments, DateTime startDate, DateTime endDate)
    : base(MoeState.New)
{
    this.Id = "-1";
    this.OfferSettingId = "-1";
    this.SettingCode = settingCode;
    this.AccountId = accountId;
    this.Arguments = arguments;
    this.StartDate = startDate;
    this.EndDate = endDate; //here it is 3155378975990000000
}

Any ideas?

Chris Mantle
  • 6,595
  • 3
  • 34
  • 48
jbenscoter
  • 171
  • 1
  • 2
  • 11

4 Answers4

1

I have a no-repro - I just tried it and can't get it to repro. You will need to debug and if it makes it easy, rewrite the code to assign row["EndDate"] to a variable (even if temporarily) so you can at least see what's in that variable.

FYI, in your second condition, you seem to be testing for row["EndDate"] along with row["StartDate"], which might be contributing to the issue.

(Equals(row["EndDate"], "") || Equals(row["StartDate"], DBNull.Value)) ? dt : Convert.ToDateTime(row["EndDate"]));

As others suggested:

  • Try Nullable instead of MaxValue. You are likely to run into issues with different time zones and locales without even realizing (esp., e.g. when your code runs on different machines).
  • Consider using DateTimeOffset instead of DateTime, as it represents 'instantaneous time' instead of 'calendar time'. See here for more discussion. (You'd rather ideally still use Nullable.)
Community
  • 1
  • 1
Omer Iqbal
  • 2,245
  • 10
  • 15
  • I will be checking out Nullable today, did not know it existed until CodeCaster pointed it out above. Also, I just figured it out, it was passing the wrong value into the constuctor. – jbenscoter Jun 16 '14 at 20:38
  • Good catch on the Equals, that was incorrect, Thanks! – jbenscoter Jun 16 '14 at 20:40
0

Nullable DateTime struct would be named DateTime? e.g.

DateTime? ndt=null;

You also would need to check if(HasValue()), before poking the actual value field.

if(ndt.HasValue()){/*do what you meant to */}
0

I figured it out, I am just an idiot, it was passing the wrong value to the constructor.

jbenscoter
  • 171
  • 1
  • 2
  • 11
0

Simply passing a value through a constructor parameter absolutely cannot change the value, so you can eliminate that part of it.

It's more likely that there is an issue with precision loss. This might happen either when you store the value into the database, or when you're retrieving it.

On the storage side, if you really need to store the full precision of DateTime.MaxValue, then make sure you're using a data type in your database that can support it. For example, if you're using SQL Server, you should use a datetime2 type rather than a datetime type.

On the retrieving side, some of your code appears to be suffering from a common anti-pattern.

  • Don't do this:

    DateTime dt = Convert.ToDateTime(row["yourfield"].ToString());
    
  • Instead, do this:

    DateTime dt = (DateTime) row["yourfield"];
    

When you convert to a string and then parse that string, there can be a loss of precision. Also, culture-specific formatting or non-Gregorian calendars can get in the way in certain cases. By simply unboxing it instead, you keep it in the original type. No strings required.

Same goes for other types, including integers, booleans and strings. The underlying database client has already made the best conversion from the native database type to an appropriate .Net type. No need to do that work again.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575