.NET framework2.0中的农历类(三)写自已的日期格式化器

五、写自已的日期格式化器

昨天看了一篇文章,说目前大家用的“农历”这个术语是文革时期才有的,目的是反封建。这里为了省事,还是继续使用这个术语。而英文名称ChineseLunisolarCalendar太长,我自己的代码中就用ChineseCalendar为相关功能命名,这个名字也还过得去吧。

我原先设想自定义一个类,使得能写出这样的代码:

string  s =  DateTime.Now.ToString( new  MyFormatProvider());
就能得出我想要的农历日期字符串,经过测试却失败了,依据我的分析,微软公司在.net框架中把日期时间型的格式写死了,只能依据相关的地区采用固定的几种显示格式,没法再自行定义。而前文已经说过,而所有的相关格式微软公司都放到一个名为culture.nlp的文件中(这个文件在以前的.net框架是一个独立的文件,在.net 2.0被作为一个资源编译到mscorlib.dll中。) (我的这个不能为DateTime写自已的格式化器的观点没有资料佐证,如有不当之处,请大家指正)

 

虽然不能为DataTime写自定义的格式器,但还有另外一个途径,就是为String类的Format方法写自定义格式化器,我测试了一下,效果还不错,调用方式如下:

string  s =  String.Format( new  ChineseCalendarFormatter(),  " {0:D} " ,DateTime.Now);

可以得到“二〇〇六年正月初九”

 

string  s =  String.Format( new  ChineseCalendarFormatter(),  " {0:d} " ,DateTime.Now);

可以得到“丙戌年正月初九”

 

虽然没有前面所设想的方便,但也还能接受,全部代码帖出如下:

第一个类,主要是封装了农历的一些常用字符和对日历处理的最基本功能

using  System;
using  System.Collections.Generic;
using  System.Text;

using  System.Globalization;

public   static   class  ChineseCalendarHelper
{
    
public   static   string  GetYear(DateTime time)
    {
        StringBuilder sb 
=   new  StringBuilder();
        
int  year  =  calendar.GetYear(time);
        
int  d;
        
do
        {
            d 
=  year  %   10 ;
            sb.Insert(
0 , ChineseNumber[d]);
            year 
=  year  /   10 ;
        } 
while  (year  >   0 );
        
return  sb.ToString();
    }

    
public   static   string  GetMonth(DateTime time)
    {
        
int  month  =  calendar.GetMonth(time);
        
int  year  =  calendar.GetYear(time);
        
int  leap  =   0 ;

        
// 正月不可能闰月
         for  ( int  i  =   3 ; i  <=  month; i ++ )
        {
            
if  (calendar.IsLeapMonth(year, i))
            {
                leap 
=  i;
                
break ;   // 一年中最多有一个闰月
            }

        }
        
if  (leap  >   0 ) month -- ;
        
return  (leap  ==  month  +   1   ?   " "  :  "" +  ChineseMonthName[month  -   1 ];
    }

    
public   static   string  GetDay(DateTime time)
    {
        
return  ChineseDayName[calendar.GetDayOfMonth(time)  -   1 ];
    }

    
public   static   string  GetStemBranch(DateTime time)
    {
        
int  sexagenaryYear  =  calendar.GetSexagenaryYear(time);
        
string  stemBranch  =  CelestialStem.Substring(sexagenaryYear  %   10   -   1 1 +
                      TerrestrialBranch.Substring(sexagenaryYear  %   12   -   1 1 );
        
return  stemBranch;
    }

    
private   static  ChineseLunisolarCalendar calendar  =   new  ChineseLunisolarCalendar();
    
private   static   string  ChineseNumber  =   " 〇一二三四五六七八九 " ;
    
public   const   string  CelestialStem  =   " 甲乙丙丁戊己庚辛壬癸 " ;
    
public   const   string  TerrestrialBranch  =   " 子丑寅卯辰巳午未申酉戌亥 " ;
    
public   static   readonly   string [] ChineseDayName  =   new   string [] {
            " 初一 " , " 初二 " , " 初三 " , " 初四 " , " 初五 " , " 初六 " , " 初七 " , " 初八 " , " 初九 " , " 初十 " ,
            
" 十一 " , " 十二 " , " 十三 " , " 十四 " , " 十五 " , " 十六 " , " 十七 " , " 十八 " , " 十九 " , " 二十 " ,
            
" 廿一 " , " 廿二 " , " 廿三 " , " 廿四 " , " 廿五 " , " 廿六 " , " 廿七 " , " 廿八 " , " 廿九 " , " 三十 " };
    
public   static   readonly   string [] ChineseMonthName  =   new   string []
           " " " " " " " " " " " " " " " " " " " " " 十一 " " 十二 "  };
}

第二个类为自定义格式化器:
using  System;
using  System.Collections.Generic;
using  System.Text;

using  System.Globalization;
using  System.Threading;

public   class  ChineseCalendarFormatter : IFormatProvider, ICustomFormatter
{
    
// 实现IFormatProvider
     public   object  GetFormat(Type formatType)
    {
        
if  (formatType  ==   typeof (ICustomFormatter))
            
return   this ;
        
else
            
return  Thread.CurrentThread.CurrentCulture.GetFormat(formatType);
    }

    
// 实现ICustomFormatter
     public   string  Format( string  format,  object  arg, IFormatProvider formatProvider)
    {
        
string  s;
        IFormattable formattable 
=  arg  as  IFormattable;
        
if  (formattable  ==   null )
            s 
=  arg.ToString();
        
else
            s 
=  formattable.ToString(format, formatProvider);
        
if  (arg.GetType()  ==   typeof (DateTime))
        {
            DateTime time 
=  (DateTime)arg;
            
switch  (format)
            {
                
case   " D " // 长日期格式
                    s  =  String.Format( " {0}年{1}月{2} " ,
                        ChineseCalendarHelper.GetYear(time),
                        ChineseCalendarHelper.GetMonth(time),
                        ChineseCalendarHelper.GetDay(time));
                    
break ;
                
case   " d " // 短日期格式
                    s  =  String.Format( " {0}年{1}月{2} " , ChineseCalendarHelper.GetStemBranch(time),
                        ChineseCalendarHelper.GetMonth(time),
                        ChineseCalendarHelper.GetDay(time));
                    
break ;
                
case   " M " // 月日格式
                    s  =  String.Format( " {0}月{1} " , ChineseCalendarHelper.GetMonth(time),
                        ChineseCalendarHelper.GetDay(time));
                    
break ;
                
case   " Y " // 年月格式
                    s  =  String.Format( " {0}年{1}月 " , ChineseCalendarHelper.GetYear(time),
                        ChineseCalendarHelper.GetMonth(time));
                    
break ;
                
default :
                    s 
=  String.Format( " {0}年{1}月{2} " , ChineseCalendarHelper.GetYear(time),
                        ChineseCalendarHelper.GetMonth(time),
                        ChineseCalendarHelper.GetDay(time));
                    
break ;
            }
        }
        
return  s;
    }
}
这段代码中间处理格式那部份稍做改进,就可以支持更多的日期格式。

有了这两段代码为原型,要实现计算和显示一个日期的农历日期及其它功能,基本上就很容易了。

你可能感兴趣的:(.NET framework2.0中的农历类(三)写自已的日期格式化器)