How can I show a string representation of a nullable DateTime type?

438 Views Asked by At

The user supplies "from" and "to" months for a report to be generated (e.g., from 1 month back to 13 months back; if they choose this on 2/15/2016, the return values are 1/1/2015 and 1/1/2016).

I want to allow the user to select either the furthest back or the nearest month from either the "from" or the "to" combobox. I just want to use the furthest back in time as the "from" and the closest in time as the "to" to avoid confusion on their part (they can do whatever seems natural to them).

So I start off with this code:

int fromMonths = Convert.ToInt32(comboBoxProduceUsageFrom.Text);
DateTime RptParamsNominalFromDate = ReportSchedulerConstsAndUtils.SubtractMonthsFrom(fromMonths, nextGenerateAndSendDate);
int toMonths = Convert.ToInt32(comboBoxProduceUsageTo.Text);
DateTime RptParamsNominalToDate = ReportSchedulerConstsAndUtils.SubtractMonthsFrom(toMonths, nextGenerateAndSendDate);

..and then I want to set the "from" date to the furthest back in time and the "to" to the nearer in time. I first tried this:

DateTime RptParamsFromDate;
DateTime RptParamsToDate;
if (RptParamsNominalFromDate > RptParamsNominalToDate)
{
    RptParamsFromDate = RptParamsNominalToDate;
    RptParamsToDate = RptParamsNominalFromDate;
}
else if (RptParamsNominalToDate > RptParamsNominalFromDate)
{
    RptParamsFromDate = RptParamsNominalFromDate;
    RptParamsToDate = RptParamsNominalToDate;
}

...but that fails with, "Use of unassigned local variable 'RptParamsFromDate'" (and the same error for "RptParamsToDate").

So I tried giving the DateTimes a value/nonvalue like so:

DateTime RptParamsFromDate = null;
DateTime RptParamsToDate = null;

...but that gives me, "Cannot convert null to 'System.DateTime' because it is a non-nullable value type"

So I set my fingers in motion again and tried nullablizing the DateTimes:

DateTime? RptParamsFromDate = null;
DateTime? RptParamsToDate = null;

...but then I get, "'System.Nullable' does not contain a definition for 'ToLongDateString' and no extension method 'ToLongDateString' accepting a first argument of type 'System.Nullable' could be found (are you missing a using directive or an assembly reference?)"

This is due to this code:

RptParamsFromDate.ToLongDateString()

in this block:

MessageBox.Show(string.Format(
    "Using the current configuration, the Produce Usage report would next be sent on {0} and emailed to {1}; the report would cover data from {2} to {3}",
    nextGenerateAndSendDate.ToLongDateString(), 
    emailRecipients,
    RptParamsFromDate.ToLongDateString(),
    RptParamsToDate.ToLongDateString()));

So what can I do to show the DateTime value and still appease the cantankerous beast?

UPDATE

Incorporating info from both SLaks and crashmstr, I ended up with the following working method:

private void buttonTestProdUsageSettings_Click(object sender, EventArgs e)
{
    // Show example of when the report will run, and using which parameters,
    // using the current configuration
    DateTime nextGenerateAndSendDate = GetNextProduceUsageGenerateAndSendDate();
    string emailRecipients = string.Join(",", emailAddresses.ToArray());
    int fromMonths = Convert.ToInt32(comboBoxProduceUsageFrom.Text);
    DateTime RptParamsNominalFromDate = ReportSchedulerConstsAndUtils.SubtractMonthsFrom(fromMonths, nextGenerateAndSendDate);
    int toMonths = Convert.ToInt32(comboBoxProduceUsageTo.Text);
    DateTime RptParamsNominalToDate = ReportSchedulerConstsAndUtils.SubtractMonthsFrom(toMonths, nextGenerateAndSendDate);
    if (RptParamsNominalFromDate.Equals(RptParamsNominalToDate))
    {
        MessageBox.Show("The \"from\" and \"to\" values must differ; please try again.");
        return;
    }

    // Allow user to enter either the nearest or furthest value in either the "from" or the "to":
    DateTime? RptParamsFromDate = null;
    DateTime? RptParamsToDate = null;
    if (RptParamsNominalFromDate > RptParamsNominalToDate)
    {
        RptParamsFromDate = RptParamsNominalToDate;
        RptParamsToDate = RptParamsNominalFromDate;
    }
    else if (RptParamsNominalToDate > RptParamsNominalFromDate)
    {
        RptParamsFromDate = RptParamsNominalFromDate;
        RptParamsToDate = RptParamsNominalToDate;
    }

    MessageBox.Show(string.Format(
        "Using the current configuration, the Produce Usage report would next be sent on {0} and emailed to {1}; the report would cover data from {2} to {3}",
        nextGenerateAndSendDate.ToLongDateString(), 
        emailRecipients,
        RptParamsFromDate.HasValue ? RptParamsFromDate.Value.ToLongDateString() : "No \"from\" Date",
        RptParamsToDate.HasValue ? RptParamsToDate.Value.ToLongDateString() : "No \"to\" Date"));
}
2

There are 2 best solutions below

0
On BEST ANSWER

You're trying to use the value of a nullable type.

To do that, you need to access its .Value property, which returns a regular DateTime value.

Beware that that will throw an exception if it is in fact null.

2
On

To add on to Slaks's original answer, the reason you were getting the first answer was because you must be trying to reference RptParamsFromDate or its kin, later in the code. The problem is because of this:

You've done:

  1. Create Variable
  2. Is something true? No? ...okay
  3. Is something else true? No? ...okay
  4. Variable has still not been set to anything. (Because RptParamsNominalFromDate == RptParamsNominalToDate)
  5. (Assumption) You've tried to access the variable.

Use of unassigned local variable 'RptParamsFromDate'" (and the same error for "RptParamsToDate

Setting it to a DateTime? will get past that, somewhat, but you need to look into the logic issue, first. Make sure you're checking that this is null, before you try to use it, later.