mono의 한국어 DateTimeFormatInfo

FreeBSD에서 mono가 여전히 잘 안되는 부분이 많기에.. 고치기도 힘들고 해서 깔아놓고는 별로 안 쓰고 있었는데, 창우옹께서 날짜가 이상하게 나오는 문제가 있다기에, 주말에 날씨도 화창한데 집에서 문제를 고쳐 봤습니다.

우선, 문제는 System.DateTime.ToShortTimeString()의 결과가 “오 5:12″같이 오전/오후가 표시가 안 되는 생뚱맞은 것이었는데, MS.NET CLR에서는 “오후 5:12″로 제대로 나왔는데, mono에서만 짤려서 나오는 것이었습니다. 그래서 무슨 문제인지 추적을 해 봤는데.. 역시 구조는 여기 저기 많이 거친거라.. 한참을 “그건 우리 담당이 아니니 다른 데 가서 알아보세요”를 겪고 찾아버렸습니다. 으흐.

  • 일단은 corlib의 System.DateTime 클래스: 여기서는 ShortTimeString 메쏘드가 ToString 메쏘드를 호출하고, ToString에서는 내부적인 다른 메쏘드에서 System.Globalization.DateTimeFormatInfo 클래스의 ShortTimePattern을 참조하고 있었습니다.
  • System.Globalization.DateTimeFormatInfo을 보니까, 별다른 내용은 없고, 그냥 다른 곳에서 construct해 준 값을 그냥 단순히 받아만 주는 것 같아서, 다시 System.DateTime으로~
  • System.DateTime 구현을 자세히 보니까 System.Globalization.CultureInfo 클래스의 인스턴스를 가져오도록 되어있었는데, 그놈이 TLS에 저장되는 전역 인스턴스를 가져오도록 되어있었습니다. 그런데, 데이터를 로딩하는 부분은 construct_datetimeformat_info()라는 정의되지도 않은 메쏘드를 쓰고 있었는데, [MethodImplAttribute (MethodImplOptions.InternalCall)] private extern void 라는 데코레이트 되는 타입으로 되어있어서, 아 이게 뭔가 하고 한참을 고민했습니다. ;;
  • 결국 mono 소스 전체에서 저 메쏘드 이름을 grep해 보니까, 와와! monoruntime의 mono/mono/metadata/locale.c에서 C함수를 그 메쏘드로 매핑하고 있었던 것.. 자세히 보니까 culture-info-table.h라는 자동 제너레이트된 파일에 datetime 포맷이 기록되어 있었습니다. 근데 그놈은 또 다른 프로그램이 만든 것;
  • 휴.. 결국은 목적지에 도착! mono/tools/locale-builder라고 하는 C#으로 작성된 프로그램이 locale과 culture관련 XML파일들을 모아서 monoruntime의 C 헤더파일로 변환을 해 주고 있었습니다. mono에서는 ICU의 데이터들을 그대로 쓰고 있는데, ICU LDML와 CLI의 포맷이 다른 점을 supp/ 디렉터리 아래의 xml 파일들로 오버라이드하고 있는 바로 그 부분에서 잘못된 포맷이 있었던 것! 그래서 잽싸게 쓱싹 수정해서..
  • 버그를 질렀습니다. 으흐.. 버그질라는 왜이리 복잡하지~

그런데, 이번에 이 작업을 하면서, mono의 System.Globalization 지원 부분의 내부 구조를 잘 알게 되었는데, 생각보다는 역시 디자인이 괜찮은 것이, 파이썬에도 CultureInfo같은 것을 하나 만들어 넣고 싶어졌습니다. 지금 있는 locale 모듈은 시스템 의존적이라, 안 되는게 너무 많아서.. 으흐.. 그런데, 구글에서 찾아보니 Zope X3의 zope.i18n 쪽에서 ICU를 기반으로 한 국제화 지원이 들어가고 있었는데, 아직 구체적으로는 안 봤지만 뭔가 기대가 됩니다!

4 thoughts on “mono의 한국어 DateTimeFormatInfo”

  1. 와와~ 고마워요~

    저는 두 단계까지 들어가서 “다른데 가서 알아보세요”라길래 포기했는데.

  2. Pingback: Changwoo's Hacks

Comments are closed.