Japanese Leap Year Date not showing correctly.

Anonymous
2024-01-11T08:22:42.6033333+00:00

Hi Team, I am trying to show leap year february date according to Japanese calendar. Era is showing correctly. But according to the era, date is showing 28 for february. I also checked if the Era 6 is leapyear. Yes, it is. But I am not getting why the date is showing as 28. Please help.


using System;

using System.Globalization;

public class Demo
{

  public static void Main ()
  {

    DateTime d1 = new DateTime (2024, 02, 29, 6, 20, 40);

    DateTime d2 = d1.AddYears (-2018);

      Console.WriteLine
      ("Initial DateTime = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ", d1);

      Console.
      WriteLine
      ("New DateTime (subtracting years) = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ",
       d2);

    JapaneseCalendar myCal = new JapaneseCalendar ();
    var s = d2.Year;
    bool r = myCal.IsLeapYear (s);

      Console.WriteLine (r);

  }

}


Output:

Initial DateTime = 29 February 2024, 06:20:40 
New DateTime (subtracting years) = 28 February 0006, 06:20:40 
True
Developer technologies | .NET | Other
Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. gekka 12,206 Reputation points MVP Volunteer Moderator
    2024-01-11T10:12:06.7733333+00:00

    Do not use addition and subtraction to calculate the year for Japanese calendar. JapaneseCalendar class has functions for this purpose. (GetEra,GetYear)

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    
    internal class Program
    {
        static void Main()
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("en-us");
    
            //System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("ja-jp");
    
            DateTime d1 = new DateTime(2024, 02, 29, 6, 20, 40, DateTimeKind.Unspecified);
            Console.WriteLine("Initial DateTime = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ", d1);
    
            JapaneseCalendar myCal = new JapaneseCalendar();
            var eraType = myCal.GetEra(d1);
            var eraYear = myCal.GetYear(d1);
            bool isLeapYear = myCal.IsLeapYear(eraYear, eraType);
    
            DateTime d2 = new DateTime(eraYear, 1, 1, 0, 0, 0, DateTimeKind.Unspecified); // For format 'y' :: If Thread is Japanese culture , 'y' will be '0006年'
    
            Console.WriteLine("New DateTime (subtracting years) = {0:dd} {1:y}, {0:hh}:{0:mm}:{0:ss}", d1, d2);
            Console.WriteLine(isLeapYear);
    
    
    
            JapaneseCalendar jpCal = new JapaneseCalendar();
            CultureInfo jpCaulture = new CultureInfo("ja-jp", false);
            jpCaulture.DateTimeFormat.Calendar = jpCal;
    
            // JapaneseCalendar has a range of dates that can be processed, and outside of that range cannot be processed correctly.
            Console.WriteLine();
            Console.WriteLine("MinSupportedDateTime=" + jpCal.MinSupportedDateTime.ToString());
            Console.WriteLine();
    
            // The first year of the Japanese calendar may begin on a day that is not January 1.
            // Therefore, simple subtraction from the Western calendar may result in the wrong year.
            // In JapaneseCalendar, GetEra,GetYear and IsLeapYear with two arguments give the correct result.
            DateTime syouwa64 = new DateTime(1989, 1, 1);
            DateTime heisei1 = new DateTime(1989, 1, 8);
            DateTime heisei2 = new DateTime(1990, 1, 1);
    
            DateTime heisei31 = new DateTime(2019, 4, 30);
            DateTime reiwa1 = new DateTime(2019, 5, 1);
    
            foreach (var dt in new[] { syouwa64, heisei1, heisei2, heisei31, reiwa1 })
            {
                string eraName = dt.ToString("gg y", jpCaulture).Split(" ")[0];
    
                Console.WriteLine($"{dt:yyyy-MM-dd}, ERA={jpCal.GetEra(dt)}, {jpCal.GetYear(dt)}, EraName={eraName}");
            }
        }
    }
    
    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Pinaki Ghatak 5,600 Reputation points Microsoft Employee Volunteer Moderator
    2024-01-11T08:36:11.3666667+00:00

    Hello 20579191 The issue you’re facing is due to the way the AddYears method works. When you subtract years from a DateTime object that represents February 29, and the resulting year is not a leap year, the date is changed to February 28. In your case, you’re subtracting 2018 years from February 29, 2024. The resulting year, 6, is not a leap year in the Gregorian calendar, so the date is changed to February 28. To maintain the day as 29 for a leap year, you could manually check if the original date was the 29th of February, and if the resulting year is a leap year, then set the day to 29. Here’s how you can modify your code:

    using System;
    using System.Globalization;
    
    public class Demo
    {
      public static void Main ()
      {
        DateTime d1 = new DateTime (2024, 02, 29, 6, 20, 40);
        int yearsToSubtract = 2018;
    
        // Subtract years
        DateTime d2 = d1.AddYears (-yearsToSubtract);
    
        // Check if original date was Feb 29 and resulting year is a leap year
        if (d1.Day == 29 && d1.Month == 2 && DateTime.IsLeapYear(d2.Year))
        {
          // Set day to 29
          d2 = new DateTime(d2.Year, d2.Month, 29, d2.Hour, d2.Minute, d2.Second);
        }
    
        Console.WriteLine("Initial DateTime = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ", d1);
        Console.WriteLine("New DateTime (subtracting years) = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ", d2);
    
        JapaneseCalendar myCal = new JapaneseCalendar();
        var s = d2.Year;
        bool r = myCal.IsLeapYear(s);
    
        Console.WriteLine(r);
      }
    }
    
    

    This code will ensure that if the original date was February 29 and the resulting year is a leap year, the day will remain as 29. Otherwise, it will be set to 28. I hope this helps.

    If this helps your issue, tagging this as answered will help other community readers who may have similar questions.

    1 person found this answer helpful.

  2. Pinaki Ghatak 5,600 Reputation points Microsoft Employee Volunteer Moderator
    2024-01-11T11:42:49.2666667+00:00

    Hello again. Here is a complete working example, taking also from @gekka

    // Set the current culture to en-us
    using System.Globalization;
    
    System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("en-us");
    
    // Create a DateTime object with a specific date and time
    DateTime d1 = new DateTime(2024, 02, 29, 6, 20, 40, DateTimeKind.Unspecified);
    Console.WriteLine("Initial DateTime = {0:dd} {0:y}, {0:hh}:{0:mm}:{0:ss} ", d1);
    
    // Create a JapaneseCalendar object
    JapaneseCalendar myCal = new JapaneseCalendar();
    
    // Get the era and year of the DateTime object
    var eraType = myCal.GetEra(d1);
    var eraYear = myCal.GetYear(d1);
    
    // Check if the year is a leap year
    bool isLeapYear = myCal.IsLeapYear(eraYear, eraType);
    
    // Create a new DateTime object with the year from the Japanese calendar
    DateTime d2 = new DateTime(eraYear, 2, 1, 0, 0, 0, DateTimeKind.Unspecified); // For format 'y' :: If Thread is Japanese culture , 'y' will be '0006年'
    
    Console.WriteLine("New DateTime (subtracting years) = {0:dd} {1:y}, {0:hh}:{0:mm}:{0:ss}", d1, d2);
    Console.WriteLine(isLeapYear);
    
    // Create a new JapaneseCalendar object
    JapaneseCalendar jpCal = new JapaneseCalendar();
    
    // Create a new CultureInfo object with the Japanese culture and set the calendar to JapaneseCalendar
    CultureInfo jpCaulture = new CultureInfo("ja-jp", false);
    jpCaulture.DateTimeFormat.Calendar = jpCal;
    
    // Output the minimum supported date and time of the Japanese calendar
    Console.WriteLine();
    Console.WriteLine("MinSupportedDateTime=" + jpCal.MinSupportedDateTime.ToString());
    Console.WriteLine();
    
    // Create DateTime objects for different eras
    DateTime syouwa64 = new DateTime(1989, 1, 1);
    DateTime heisei1 = new DateTime(1989, 1, 8);
    DateTime heisei2 = new DateTime(1990, 1, 1);
    DateTime heisei31 = new DateTime(2019, 4, 30);
    DateTime reiwa1 = new DateTime(2019, 5, 1);
    
    // Set the output encoding to Unicode
    Console.OutputEncoding = System.Text.Encoding.Unicode;
    
    // Output the era, year, and era name for each DateTime object
    foreach (var dt in new[] { syouwa64, heisei1, heisei2, heisei31, reiwa1 })
    {
        string eraName = dt.ToString("gg y", jpCaulture).Split(" ")[0];
        Console.WriteLine($"{dt:yyyy-MM-dd}, ERA={jpCal.GetEra(dt)}, {jpCal.GetYear(dt)}, EraName={eraName}");
    }
    
    

    The output now will be:

    Initial DateTime = 29 February 2024, 06:20:40
    New DateTime (subtracting years) = 29 February 0006, 06:20:40
    True
    MinSupportedDateTime=9/8/1868 12:00:00 AM
    1989-01-01, ERA=3, 64, EraName=昭和
    1989-01-08, ERA=4, 1, EraName=平成
    1990-01-01, ERA=4, 2, EraName=平成
    2019-04-30, ERA=4, 31, EraName=平成
    2019-05-01, ERA=5, 1, EraName=令和
    

    You should be able to modify this as needed, with the extensive comments applied. Does this answer your query?

    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.