2009-07-21 8 views
6

Tôi đang chuyển đổi một ứng dụng MSAccess nhỏ sang ứng dụng ASP.NET dựa trên web, sử dụng C# 3.5. Tôi đã tự hỏi cách tốt nhất để làm việc với các ngày trong C# là gì, khi chuyển đổi một số mã VBA này sang C#.Trong C#, làm thế nào để bạn chuyển đổi kiểu dữ liệu TimeSpan thành DateTime?

Dưới đây là một ví dụ của Bộ luật VBA:

Coverage1=IIf(IsNull([EffDate1]),0,IIf([CurrDate]<=[EndDate1],[CurrDate]-[EffDate1],[EndDate1]-[EffDate1]+1)) 

Đây là những gì hiện tại C# mã của tôi trông giống như với các lỗi ký hiệu trong các mã nhận xét:

public DateTime CalculateCoverageOne(DateTime dateEffDateOne, DateTime dateCurrentDate, DateTime dateEndDateOne) 
    { 
     if (dateCurrentDate.Date <= dateEndDateOne.Date) 
     { 
      return null; //Get "cannot convert null to System.DateTime because it is a non-nullable value type" error 
     } 
     else 
     { 
      if (dateCurrentDate.Date <= dateEndDateOne) 
      { 
       return dateCurrentDate.Subtract(dateEffDateOne); //Gets error "cannot implicitly convert system.timepsan to system.datetime 
      } 
      else 
      { 
       return dateEndDateOne.Subtract(dateEffDateOne.AddDays(1)); //Gets error "cannot implicitly convert system.timepsan to system.datetime 
      } 
     } 
    } 

Trả lời

2

Dường như VB của bạn thực sự đang trả về khoảng thời gian, có lẽ là trong vài ngày. Dưới đây là bản dịch trực tiếp gần nhất:

public TimeSpan CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1) 
{ 
    return (EndDate1 == null) ? TimeSpan.Zero : 
      (CurrDate < EndDate1) ? (CurrDate - EffDate1) : 
      (EndDate1.AddDays(1) - EffDate1); 
} 

Nếu thay vào đó bạn chỉ muốn có một số ngày, chỉ cần quay trở lại khách sạn Days của TimeSpan:

public int CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1) 
{ 
    return ((EndDate1 == null) ? TimeSpan.Zero : 
      (CurrDate < EndDate1) ? (CurrDate - EffDate1) : 
      (EndDate1.AddDays(1) - EffDate1)).Days; 
} 

Và đối với biện pháp tốt, đây là cách tôi sẽ dọn dẹp của bạn phiên bản cuối cùng:

public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne) 
{ 
    TimeSpan ts; 
    if (dateEffDateOne == DateTime.MinValue) 
    { 
     ts = TimeSpan.Zero; 
    } 
    else if (dateEffectiveDate <= dateEndDateOne) 
    { 
     ts = dateCurrentDate - dateEffDateOne; 
    } 
    else 
    { 
     ts = (dateEndDateOne - dateEffDateOne) + new TimeSpan(1, 0, 0, 0); 
    } 
    return ts.Days; 
} 
+0

Tuyệt vời nhất. Cảm ơn nhiều! – program247365

2

Lấy TimeSpan, sau đó trừ đi từ DateTime để lấy ngày bạn muốn. Đối với nội NẾU tuyên bố của bạn, nó sẽ trông như thế này:

TimeSpan estSpan = dateCurrentDate.Subtract(dateEffDateOne); 
return dateCurrentDate.Subtract(estSpan); 

EDIT: Bạn cũng có thể muốn quay trở lại DateTime.MaxValue và có kiểm tra chức năng gọi điện thoại cho giá trị tối đa, thay vì trả lại null.

+0

Mã của bạn sẽ luôn trả về ngàyEffDateOne do đó, không phải là sự khác biệt giữa các ngày. Tôi đoán, nó không phải là những gì @ program247365 muốn. – VladV

+0

Tôi không tin đó là những gì OP yêu cầu. Anh ta cần DateTime, nhưng nếu anh ta cần lưu trữ khoảng thời gian, thì anh ta nên sử dụng TimeSpan. –

6

không thể chuyển đổi null để System.DateTime bởi vì nó là một loại giá trị không nullable" lỗi

Loại DateTime là một loại giá trị , có nghĩa là nó không thể giữ một giá trị null. Để có được xung quanh điều này, bạn có thể làm một trong hai điều, hoặc trả về DateTime.MinValue và kiểm tra điều đó khi bạn muốn sử dụng giá trị hoặc thay đổi hàm để trả về DateTime? (lưu ý dấu hỏi), là giá trị rỗng DateTime. được sử dụng như thế này:

DateTime? nullable = DateTime.Now; 
if (nullable.HasValue) 
{ 
    // do something with nullable.Value 
} 

không thể mặc nhiên chuyển đổi system.timepsan để System.DateTime

Khi bạn trừ đi một DateTime từ DateTime khác, kết quả là một TimeSpan, đại diện cho khoảng thời gian giữa chúng. Các TimeSpan không đại diện cho một điểm cụ thể trong thời gian, nhưng khoảng chính nó. Để có được ngày, bạn có thể sử dụng phương thức Add hoặc quá tải phương thức Subtract của đối tượng DateTime chấp nhận TimeSpan. Chính xác như thế nào nên tôi không thể nói, vì tôi không biết những ngày khác nhau trong mã của bạn đại diện.

Trong trường hợp cuối cùng, bạn chỉ có thể sử dụng giá trị trả về từ phương pháp AddDays, nhưng với một giá trị âm (để trừ một ngày nào đó, thay vì thêm một ô):

return dateEffDateOne.AddDays(-1); 
+0

> dateCurrentDate.Subtract (dateCurrentDate.Subtract (dateEffDateOne)) dateCurrentDate- (dateCurrentDate-dateEffDateOne) == dateEffDateOne tôi đoán, nó không phải là những gì @ program247365 muốn. – VladV

+0

@VladV: Tôi nghĩ bạn đúng. Vì tôi không có manh mối về việc các ngày tháng khác nhau trong mẫu mã ban đầu liên quan đến nhau như thế nào nên tôi không thể tìm ra kết quả mong đợi, nên loại bỏ dòng đó khỏi câu trả lời của tôi. –

1

DateTime là một value type. Vì vậy, bạn không thể gán null cho DateTime. Nhưng bạn có thể sử dụng một giá trị đặc biệt như DateTime.MinValue để chỉ ra bất cứ điều gì bạn đang cố gắng để chỉ ra bằng null.

Ngày giờ đại diện cho một ngày (và thời gian), như "ngày 22 tháng 7 năm 2009". Điều này có nghĩa là bạn không nên sử dụng loại này để biểu thị khoảng thời gian, như là "9 ngày". TimeSpan là loại dành cho mục đích này.

dateCurrentDate.Subtract (dateEffDateOne) (hay tương đương, dateCurrentDate-dateEffDateOne) là một sự khác biệt giữa hai ngày, có nghĩa là, khoảng thời gian. Vì vậy, tôi đề nghị bạn thay đổi kiểu trả về của hàm thành TimeSpan.

TimeSpan cũng là một loại giá trị, vì vậy bạn có thể sử dụng, ví dụ, TimeSpan.Zero thay vì null.

0

Sau một số câu trả lời tuyệt vời (tôi đã bình chọn cho các bạn), tôi cuối cùng đã nghĩ ra câu trả lời của mình. Hóa ra là quay trở lại một int, như số ngày, là những gì làm việc cho tôi trong tình huống này.

Cảm ơn mọi người, vì đã cung cấp câu trả lời tuyệt vời của bạn. Nó giúp tôi đi đúng hướng.

public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne) 
    { 
     //Coverage1= 
     //IIf(IsNull([EffDate1]),0, 
      //IIf([CurrDate]<=[EndDate1], 
       //[CurrDate]-[EffDate1], 
        //[EndDate1]-[EffDate1]+1)) 

     if (dateEffDateOne.Equals(TimeSpan.Zero)) 
     { 
      return (TimeSpan.Zero).Days; 
     } 
     else 
     { 
      if (dateEffectiveDate <= dateEndDateOne) 
      { 
       return (dateCurrentDate - dateEffDateOne).Days; 
      } 
      else 
      { 
       return (dateEndDateOne - dateEffDateOne).Add(new TimeSpan(1, 0, 0, 0)).Days; 
      } 
     } 
    } 
+0

Bạn có thể có nghĩa là dateEffDateOne.Equals (DateTime.MinValue) thay vì TimeSpan.Zero. Trong thực tế, chúng giống nhau (được lưu trữ dưới dạng 0L), nhưng bạn không nên dựa vào sự trùng hợp ngẫu nhiên đó. – dahlbyk

+0

Gotcha. Cảm ơn bạn đã bình luận. – program247365