簡體   English   中英

C#在幾個月內有所不同?

[英]C# get difference in months?

我正在C#開發一個項目。 我有一個名為ExamResult的模型,它有一個名為Date的字段,定義為String

然后我定義以下內容

        var executionQuery = (from x in db.ExamResult
                     where x.Student.Equals(iStudent)
                     orderby x.Date
                     select *);

Date以<YEAR>-<MONTH>格式獲取值,如下所示

2014-01
2013-04
2013-09

我想要做的是創建一個表,該表獲取返回的所有日期的最小值,並創建一個與最小日期相差幾個月的表。

例:

當我們得到如上所示的結果時,我想獲得下表(如果我們得到的最小值是2013-04)

9
0
5

我嘗試執行以下操作但是我收到了System.NotSupported異常

var dates = executionQuery.Select(x => int.Parse(x.Date.Substring(0,
4)) * 12 + int.Parse(x.Date.Substring(5, 2)) -
int.Parse(minDate.Substring(0, 4)) * 12 -
int.Parse(minDate.Substring(5, 2)));

你知道我怎么做嗎?

將字符串轉換為實際的“DateTime”對象將使事情變得更簡單。

// Getting DateTime objects instead of strings
var dates = executionQuery.ToArray().Select(
                 x => DateTime.ParseExact(x.Date,"yyyy-MM", CultureInfo.InvariantCulture));

// calculating smallest date
var minDate = dates.Min(x => x);

// this will help you get a collection of integers  
var diffDates = dates.Select(
               x => ((x.Year - minDate.Year) * 12) + x.Month - minDate.Month);

我使用一個小的Func<TIn, TOut>委托將您的字符串日期轉換為DateTimes,然后它們可以正確排序。

首先,將日期字符串轉換為DateTime對象的簡單方法:

// Split the string and instantiate new DateTime object to sort by later
Func<string, DateTime> getDate = s => {
    int[] dateParts = s
        .Split(new char[] {'-'})
        .Select(dp => int.Parse(dp))
        .ToArray();

    // Let's use the new DateTime(int year, int month, int day) constructor overload
    // dateParts[0] is the year and dateParts[1] is the month;
    // the magic number 1 below  is just a day to give to the DateTime constructor
    return new DateTime(dateParts[0], dateParts[1], 1); 
};

您的代碼可能看起來像這樣; 我無法測試您的代碼,因此這取決於您是否可以使其工作:

注意我將您的Linq查詢分開並在C#中進行排序; 所以你可以隨心所欲地從數據庫中獲取東西,然后訂購這些東西。 我希望這有效; 否則,你必須兩次調用我的getDate Func - 一次在orderby ,一次在select ; 我不喜歡那個選擇。

// The select now builds an anonymous object; You can also create a new class, ExamResultWithDate,
// for example, that has all fields of ExamResult plus a DateTime field; OR you can just add that 
// property to the partial class generated by EF or Linq-to-Sql or whatever right on the ExamResult 
// entity.

var executionQuery = (from x in db.ExamResult
                     where x.Student.Equals(iStudent)
                     select new { Entity = x, ActualDate = getDate(x.Date) }); // note select * as in your OP doesn't compile :)

var orderedQuery = executionQuery
    .OrderBy(eq => eq.ActualDate)
    .Select(er => er.Entity); // gets you just the entities in this case and discards the dates

要獲得有差異的日期,只需在最短的日期做一些簡單的計算:這也是你的程序的偽代碼;

// Let's get the minimum date and difference in months;
DateTime minDate = executionQuery
    .ToList()
    .Select(o => o.ActualDate)
    .Min();

// I am just using the dates here but you can easily use your entire entity or whatever you need
Dictionary<DateTime, int> datesWithMonthDifference = executionQuery
    .ToDictionary(
        eq => eq.ActualDate
        eq => ((eq.Year - minDate.Year) * 12) + eq.Month - minDate.Month // this formula calculates month difference as an integer 
    );

這是一個可以滿足您需求的工作程序:請注意,這只是一個需要適合您的項目的示例。

using System;
using System.Collections.Generic;
using System.Linq;

namespace DateTimeFromString
{
    class Program
    {

        static void Main(string[] args)
        {

            List<string> dates = new List<string>()
            {
                "2014-01",
                "2013-04",
                "2013-09"
            };

            // Split the string and instantiate new DateTime object to sort by later
            Func<string, DateTime> getDate = s => {
                int[] dateParts = s
                    .Split(new char[] {'-'})
                    .Select(dp => int.Parse(dp))
                    .ToArray();

                // Let's use the new DateTime(int year, int month, int day) constructor overload
                // dateParts[0] is the year and dateParts[1] is the month;
                // the magic number 1 below  is just a day to give to the DateTime constructor
                return new DateTime(dateParts[0], dateParts[1], 1); 
            };

            List<DateTime> sortedDates = dates
                .Select(d => getDate(d))
                .OrderBy(d => d)
                .ToList();

            Console.WriteLine(" Sorted Dates: ");
            sortedDates.ForEach(d => Console.WriteLine(d.Year.ToString() + " - " + d.Month.ToString()));

            // Let's get the minimum date and difference in months;
            DateTime minDate = sortedDates.Min();

            Dictionary<DateTime, int> datesWithMonthDifference = sortedDates
                .ToDictionary(
                    sd => sd,
                    sd => ((sd.Year - minDate.Year) * 12) + sd.Month - minDate.Month
                );

            Console.WriteLine();
            Console.WriteLine("Sorted dates with month difference:");

            foreach (var key in datesWithMonthDifference.Keys)
            {
                Console.WriteLine("{0} has difference of {1}", key, datesWithMonthDifference[key]);
            }
            Console.ReadKey();
        }
    }
}

我的測試程序的結果如下所示:

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM