【问题标题】:How to convert Persian Calendar date string to DateTime?如何将波斯日历日期字符串转换为 DateTime?
【发布时间】:2022-04-08 06:20:25
【问题描述】:

我使用这些代码来转换当前日期时间并减去用户在文本框中键入的日期时间。但是在转换时会出错。

PersianCalendar p = new System.Globalization.PersianCalendar();
DateTime date = new DateTime();
date = DateTime.Parse(DateTime.Now.ToShortDateString());
int year = p.GetYear(date);
int month = p.GetMonth(date);
int day = p.GetDayOfMonth(date);
string str = string.Format("{0}/{1}/{2}", year, month, day);
DateTime d1 = DateTime.Parse(str);
DateTime d2 = DateTime.Parse(textBox9.Text);
string s = (d2 - d1).ToString().Replace(".00:00:00", "");
textBox10.Text = (d2 - d1).ToString().Replace(".00:00:00","");

此行在将日期时间从字符串转换为日期时间时会报错:DateTime d1 = DateTime.Parse(str);

请帮我解决这个问题。

提前致谢

【问题讨论】:

  • 为什么要格式化 DateTime.Now 然后再解析呢?为什么要给date 赋值,然后立即给它赋值?你为什么要解析波斯年/月/日,就好像它不在波斯日历中一样? 非常不清楚您要做什么,以及波斯历法适合的位置。
  • 你不会对你的string s做任何事情。
  • 您当前文化的日期格式是否设置为波斯语?
  • @Tejs 字符串未被识别为有效的日期时间。
  • 您当前的文化是否设置为使用该格式?通常,它会期望mm/dd/yyyy 格式,这显然会因您的str 构造而失败。不同的文化会改变所需的格式。

标签: c# datetime


【解决方案1】:

这里不需要解析日期。

编辑:

最初我只想用这个答案指出 OP 处理中的错误。 但我认为完整的答案会更好(尽管有延迟:)) 是的,我知道中间日期表示看起来不像波斯日期。但这不是所需要的。此代码在当前日期和用户输入的日期之间给出了适当的差异。

string userInput = "1394/02/31";
System.DateTime date = System.DateTime.Today;
System.Globalization.PersianCalendar p = new System.Globalization.PersianCalendar();

int year = p.GetYear(date);
int month = p.GetMonth(date);
int day = p.GetDayOfMonth(date);
System.DateTime currentDate = new System.DateTime(year, month, 1);
currentDate = currentDate.AddDays(day - 1);

// validation omitted
System.String[] userDateParts = userInput.Split(new[] { "/" }, System.StringSplitOptions.None);
int userYear = int.Parse(userDateParts[0]);
int userMonth = int.Parse(userDateParts[1]);
int userDay = int.Parse(userDateParts[2]);
System.DateTime userDate = new System.DateTime(userYear, userMonth, 1);
userDate = userDate.AddDays(userDay - 1);

System.TimeSpan difference = currentDate.Subtract(userDate);

【讨论】:

  • 还是和DateTime d1 = DateTime.Now.Date一样。
  • @GrzegorzWilczura 它说:年、月和日参数描述了一个无法表示的日期时间。
  • @Grzegorz:对不起,你是对的。我对波斯日历一无所知。我以为它只是使用了不同的格式,不知道它是一个完全不同的日历。
  • 最后一行尝试创建一个公历日期,其中包含相当于今天的波斯文的年、月和日。我不认为每个波斯日期也是有效的公历日期。例如,波斯历第二个月有 31 天,但二月没有 31 天。
  • @GrzegorzWilczura 那我该怎么办?
【解决方案2】:

您的实际问题似乎在于解析用户以波斯日历格式输入的日期。因此,如果用户输入1391/2/31,您希望能够解析它。今天(2012 年 5 月 19 日)是 1391/2/30,所以您最终想要显示类似 1 day remaining 的内容。

这个问题有been asked before。但是,那里接受的答案只是尝试使用

string persianDate = "1390/02/07";
CultureInfo persianCulture = new CultureInfo("fa-IR");
DateTime persianDateTime = DateTime.ParseExact(persianDate, 
    "yyyy/MM/dd", persianCulture);

这不适用于1391/2/31 这样的日期。所以我认为你必须自己实现解析。

不执行任何错误检查,并假设用户始终使用yyyy/mm/dd 格式,您可以使用:

// Convert Persian Calendar date to regular DateTime
var persianDateMatch = System.Text.RegularExpressions.Regex.Match(
    persianTargetTextBox.Text, @"^(\d+)/(\d+)/(\d+)$");
var year = int.Parse(persianDateMatch.Groups[1].Value);
var month = int.Parse(persianDateMatch.Groups[2].Value);
var day = int.Parse(persianDateMatch.Groups[3].Value);
var pc = new System.Globalization.PersianCalendar();
var target = pc.ToDateTime(year, month, day, 0, 0, 0, 0);

var difference = target - DateTime.Today;
differenceLabel.Text = difference.TotalDays.ToString("0");

您需要检查正则表达式是否真的找到任何匹配项。您还必须检查 pc.ToDateTime 是否不会引发错误。不幸的是,波斯历法似乎不存在像DateTime.TryParse 这样的东西。

反正今天不需要解析成波斯日历,只需要解析用户输入即可。

您可能还对Farsi Library - Working with Dates, Calendars, and DatePickers 感兴趣,尽管这篇文章已经很老了(2007 年)。

【讨论】:

    【解决方案3】:

    只需在PersianCalendar 类上使用ToDateTime 方法:

    PersianCalendar p = new PersianCalendar();
    DateTime now = DateTime.Now;
    DateTime dateT = p.ToDateTime(now.Year, now.Month, now.Day, 0, 0, 0, 0);
    

    然后以该格式获取您的字符串,只需执行以下操作:

    string str = dateT.ToShortDateString();
    

    【讨论】:

    • 此方法将波斯历转换为我们的日期。所以实际上,你会在遥远的未来得到一些东西。我怀疑这就是他想要的。
    • @GrzegorzWilczura 它转换为我们的日子,使用波斯历法,那将来会给你什么?
    【解决方案4】:

    我解决了这个问题。这是因为在某些月份出现异常,所以如果你想减去两个日期时间,你应该将两者都转换为公历,然后你可以减去它们并查看结果。

    代码如下:

    PersianCalendar p = new PersianCalendar();
            string PersianDate1 = textBox1.Text;
            string[] parts = PersianDate1.Split('/', '-');
            DateTime dta1 = p.ToDateTime(Convert.ToInt32(parts[0]), Convert.ToInt32(parts[1]), Convert.ToInt32(parts[2]), 0, 0, 0, 0);
            string PersianDate2 = textBox2.Text;
            string[] parts2 = PersianDate2.Split('/', '-');
            DateTime dta2 = p.ToDateTime(Convert.ToInt32(parts2[0]), Convert.ToInt32(parts2[1]), Convert.ToInt32(parts2[2]), 0, 0, 0, 0);
            string s = (dta2 - dta1).ToString().Replace(".00:00:00", "");
            textBox3.Text = s; // Show the result into the textbox 
    

    【讨论】:

      【解决方案5】:

      这里是你的朋友的文档:

      PersianCalendar Class

      DateTime Constructor (Int32, Int32, Int32, Calendar)

      这是您需要的确切代码:

      PersianCalendar p = new System.Globalization.PersianCalendar();
      DateTime today = DateTime.Today;
      DateTime pDate = new DateTime(p.GetYear(today), p.GetMonth(today), p.GetDayOfMonth(today), p);
      DateTime d2 = DateTime.Parse(textBox9.Text);
      // THIS NEEDS TO BE EXPLAINED
      textBox10.Text = (d2 - pDate).ToString().Replace(".00:00:00","");
      

      最终,你想做什么?您对textBox10 的预期结果是什么?如果您想要两个日期之间的天数,那么只需执行(d2 - pDate).ToString("d"),您就会得到天数的差异。也许如果您进一步解释您要做什么,而不是您要如何做,我们可能会为您提供进一步的帮助。

      编辑:刚刚意识到康梅在说什么。会导致问题的行在这里:

      DateTime d2 = DateTime.Parse(textBox9.Text);
      

      相反,我们需要将其更改为也使用文化信息:

      CultureInfo persianCulture = new CultureInfo("fa-IR");
      DateTime d2 = DateTime.Parse(textBox9.Text, persianCulture)
      

      编辑:你是对的,它只允许解析波斯格式的日期,但不根据特定的日历进行验证。为了使其正常工作,您必须手动解析日期并使用提供的 PersianCalendar 实例化一个新的 DateTime:

      DateTime d2;
      if(Regex.IsMatch(textBox9.Text, "^dddd/dd/dd$"))
      {
          d2 = new DateTime(
              int.Parse(textBox9.Substring(0,4)), 
              int.Parse(textBox9.Substring(5, 2)), 
              int.Parse(textBox9.Substring(8, 2)),
              p);
      }
      

      您只需要确保输入与您指定的格式完全匹配,否则无法始终准确地解析出 DateTime。

      【讨论】:

      • 我认为您不能从每个可能的波斯日期创建 DateTime。波斯第 2 个月有 31 天,但公历日期没有。所以它会在new DateTime(1391,2,31);之类的东西上失败。
      • @comecme:这是有效的,因为您也在提供日历,这意味着它会根据特定日历验证日期。 @aliboy38:当然可以,因为时间跨度是负数(意味着用户输入的日期早于今天的日期)。如果用户提供的日期将小于今天的日期,则颠倒日期时间减法的顺序 ((pDate-d2).ToString("d"))。不过,这又取决于您要完成的工作。如果您只想要天数部分(绝对值),那么只需执行Math.Abs((pDate - d2).TotalDays)
      • @SPFiredrake:对不起,我不得不滚动您的代码才能看到您提供 p 作为最后一个参数。但是解析将是另一个问题,您现在已经解决了。
      • 您的pDatetoday 完全相同。此外,使用 CultureInfo("fa-IR") 仅定义格式 yyyy/mm/dd,但不允许使用波斯日历日期(如 1391/2/30,即今天)。
      【解决方案6】:

      您还可以使用以下 .net 库来像使用 DateTime 一样简单地使用 PersianCalendar:

      Persian Calendar(PersianDateTime) in C#

      var persianDateTime = PersianDateTime.Now;
      Console.Write(persianDateTime.ToString());
      

      【讨论】:

        【解决方案7】:

        您可以使用此代码:

          DateTime today = DateTime.Today; // excludes h/m/s
        
          DateTime userdate = DateTime.Parse(textBox9.Text);
        

        如果你从另一个中减去一个,你会得到一个 TimeSpan。

          TimeSpan diff = today - userDate;
        

        您可以使用此时间跨度的属性以您喜欢的方式显示它们。

        要管理转换表格/到波斯历,您有一个很好的解决方案:

        .NET How to parse a date string for Persian (Jalali calendar) into a DateTime object?

        参考资料:

        DateTime.Today

        TimeSpan

        【讨论】:

          【解决方案8】:

          这是我正在使用的代码:

            public DateTime ConvertPersianToEnglish(string persianDate)
                  {
                      string[] formats = { "yyyy/MM/dd", "yyyy/M/d", "yyyy/MM/d", "yyyy/M/dd" };
                      DateTime d1 = DateTime.ParseExact(persianDate, formats,
                                                        CultureInfo.CurrentCulture, DateTimeStyles.None);
                      PersianCalendar persian_date = new PersianCalendar();
                      DateTime dt = persian_date.ToDateTime(d1.Year, d1.Month, d1.Day, 0, 0, 0, 0, 0);
                      return dt;
                  }
          

          【讨论】:

            【解决方案9】:

            使用Noda Time 可以更轻松地完成此操作:

            using System.Globalization;
            using NodaTime;
            using NodaTime.Text;
            
            ...
            
            CultureInfo culture = CultureInfo.CreateSpecificCulture("fa-IR");
            CalendarSystem calendar = CalendarSystem.GetPersianCalendar();
            LocalDate template = new LocalDate(1, 1, 1, calendar);
            LocalDatePattern pattern = LocalDatePattern.Create("yyyy/M/d", culture, template);
            LocalDate result = pattern.Parse("1391/2/30").Value;
            
            // if you need a DateTime, then:
            DateTime dt = result.AtMidnight().ToDateTimeUnspecified();
            

            【讨论】:

              【解决方案10】:

              试试这个代码: 此代码是“grzegorz W”发布的编辑代码,但他的代码会生成错误,例如当用户输入日期 =“1394/06/31”并且错误是“年、月和日参数描述无法表示的日期时间”

              下面的代码没问题:

              string userInput = "1394/02/31";
              System.DateTime date = System.DateTime.Today;
              System.Globalization.PersianCalendar p = new System.Globalization.PersianCalendar();
              
              int year = p.GetYear(date);
              int month = p.GetMonth(date);
              int day = p.GetDayOfMonth(date);
              System.DateTime currentDate = new System.DateTime(year, month, day,p);
              
              
              System.String[] userDateParts = userInput.Split(new[] { "/" },      System.StringSplitOptions.None);
              int userYear = int.Parse(userDateParts[0]);
              int userMonth = int.Parse(userDateParts[1]);
              int userDay = int.Parse(userDateParts[2]);
              System.DateTime userDate = new System.DateTime(userYear, userMonth, userDay,p);
              
              
              System.TimeSpan difference = currentDate.Subtract(userDate);
              

              【讨论】:

                【解决方案11】:

                您可以使用这个简单的代码将 波斯历值 转换为 C# 中的 Datetime 对象并进行计算。

                DateTime dateTime 
                      = new DateTime(persianYear, persianMonth, persianDay, new PersianCalendar());
                

                【讨论】:

                  【解决方案12】:

                  您好,您可以使用此扩展方法:

                  public static class PersainDateTime
                  {
                  
                      public static DateTime PersianDateToMiladi(this string value)
                          {
                              string[] d = value.Split('/');
                              return new DateTime(int.Parse(d[0]), int.Parse(d[1]), int.Parse(d[2]), new System.Globalization.PersianCalendar());
                          }
                  }
                  

                  现在你可以在任何地方使用它:

                  var date=("1395/10/5").PersianDateToMiladi();
                  

                  var date= textbox1.text.PersianDateToMiladi();
                  

                  【讨论】:

                    【解决方案13】:
                    private void timer1_Tick(object sender, EventArgs e)
                    {
                        labelDataAD.Text = DateTime.Now.ToString("dd/MM/yyyy");
                        PersianCalendar persianCalendar = new PersianCalendar();
                        string Full = persianCalendar.GetYear(DateTime.Now) + "/" + 
                        persianCalendar.GetMonth(DateTime.Now)+"/"+ 
                        persianCalendar.GetDayOfMonth(DateTime.Now);
                        labelDataSolar.Text = string.Format("{0:yyyy\\:MM\\:dd}", Full);
                    }
                    
                    private void FormCalendar_Load(object sender, EventArgs e)
                    {           
                        timer1.Start();
                    }
                    

                    输出是:

                    【讨论】:

                    • 欢迎来到 SO。您应该在代码块中添加解释。
                    【解决方案14】:

                    对于我来说,这个解决方案可以帮助我: 我在我的项目中创建工具文件夹,然后我将类 ExtensionsHelper.cs 和 HijriDateTime.cs 和 PersianDateTime.cs 和 PersianDayOfWeek.cs 放入其中 在此链接中,您可以找到以上课程: https://github.com/Mds92/MD.PersianDateTime> 然后我使用 PersianDateTime 而不是 DateTime:

                    DateTime datetime = new DateTime(PersianDateTime.Now.Year, PersianDateTime.Now.Month, PersianDateTime.Now.Day, 0, 0, 0);
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2023-03-30
                      • 1970-01-01
                      • 2019-07-17
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多