2013-04-11 1 views
2

Мне нужно преобразовать .NET DateTime в эквивалентное представление Java Calendar.Конвертировать дату между java и .net - 2 дн.

В .NET DateTime использует Ticks так Jan 1 0001 (в .NET эпохи) в качестве лежащего в основе представления.

Java GregorianCalendar использует миллисекунды с 1 января 1970 г. (эпоха Java (или Unix)). Значение отрицательное для дат до эпохи Java, как и ожидалось.

Здесь я преобразуя DateTime представление в Millis с Java эпохи:

var dt = new DateTime(1,2,3); //way, way back. 
var javaEpoch = new DateTime(1970, 1, 1); 

var javaMillis = (dt - javaEpoch).Ticks/TimeSpan.TicksPerMillisecond; 

dt.ToString("MM/dd/yyyy").Dump();   // .Dump() is provided by LinqPad. 
javaMillis.Dump();       // Use Console.WriteLine(...) 
              // for a regular console app. 

Этот выход:

02//0001
-62132745600000

Теперь скопируйте и вставьте значение миллисекунды в этом Java сниппета:

java.util.Calendar cal = new java.util.GregorianCalendar(); 
cal.setTimeInMillis(-62132745600000L); 
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(); 
df.applyPattern("MM/dd/yyyy"); 
System.out.println(df.format(cal.getTime())); 

Этот выход:

02//0001

Я думаю, мой вопрос: Как я Я должен получить действительное значение в миллисекундах из DateTime, из которого я могу правильно построить Java-календарь?

... с подразумеваемым подзапросом «что здесь происходит?»

EDIT: Я играл с DateTimeValues ​​вокруг отсутствующего диапазона дат от юлианского до григорианского календаря (4 октября 1582 года «следует» до 15 октября 1582 года).

Для дат более поздних, чем 15 октября 1582 года, похоже, что работа прекрасна.

... Но вокруг пропавшего диапазона, DateTime начинается (или, вернее, не начало) действовать смешно:

var timespan = new DateTime(1582, 10, 15) - new DateTime(1582, 10, 4); 

возвращает набор TimeSpan из 11 дней, так что отверстие не принято с учетом операторов DateTime. Что дает? Я думал, что базовая реализация основана на System.Globalization.GregorianCalendar.

+0

Что делать, если вы используете [Joda Time] (http://joda-time.sourceforge.net/)? Ты можешь? Время в Joda улучшает стандартные даты Java и может потенциально решить вашу проблему чистым способом. Он также обеспечивает конверсии в java.util.Date и java.util.Calendar, поэтому, если вам действительно нужно использовать стандартные даты Java, вы можете использовать преобразование времени Joda для преодоления вашей проблемы. – ThanksForAllTheFish

+0

Это немного похоже на убийство мух с помощью пушки. То, что я * мог * сделать, - это изменить бит Java для вызова calendar.Set (год, месяц, день, ...) вместо calendar.SetTimeInMillis() и получить каждое из этих полей из свойств объекта .NET DateTime. Но я также хочу понять, что происходит. –

+0

Кстати, проблема, похоже, на стороне .NET рассказа - и большой JS портировал свою библиотеку на .NET: https://code.google.com/p/noda-time/ (v 1.1 выпущен просто дней назад!) –

ответ

0

Ответ 'почему':

С (декомпилируемой - спасибо dotPeek!) .NET 4 исходный код (комментарии мои):

public static DateTime operator -(DateTime d, TimeSpan t) 
{ 
    //range checks 
    long internalTicks = d.InternalTicks; 
    long num = t._ticks; 
    if (internalTicks < num || internalTicks - 3155378975999999999L > num) 
    throw new ArgumentOutOfRangeException("t", 
      Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic")); 

    else 

    //plain arithmetic using the Ticks property of the two dates. 
    return new DateTime((ulong) (internalTicks - num) | d.InternalKind); 
} 

Так что да, абсолютно никаких специальных 'григорианский' для операторов DateTime.

О «как исправить»:

я в конечном итоге использовать что-то вдоль этих линий: (псевдо-Java)

Calendar cal = new GregorianCalendar(); 
cal.set(dt.Year, dt.Month - 1 /*it's 0-based*/, dt.Day, dt.Hour, dt.Minute, dt.Second); 
cal.set(Calendar.MILLISECOND, dt.Millisecond); 
0

От Java documentation:

[...] Дата, полученная с использованием GregorianCalendar исторически точными только с 1 марта 4 AD поступательного, когда современные правилами юлианского календаря были приняты

Учитывая ваш DateTime вычитания, это только Ticks разницы, нет абсолютно никакого понятия конкретный календарь здесь. Реализация в основном return new TimeSpan(x.Ticks - y.Ticks).

Возможно, вам будет проще просто вывести дату и время ISO-8061, например 0001-02-03T00:00:00Z, который не имеет двусмысленности, а не полагается на внутреннее представление.

1

Удивительно, что никто фактически не ответил на вопрос о том, почему " дыра "существует в григорианском календаре между 4 октября 1582 и 15 октября 1582. Интересный ответ заключается в истории принятия Григорианского календаря в качестве реформы в 1582 году в Юлианском календаре. См. Wikipedia's article on Gregorian Calendar. Последний пункт в истории: григорианской реформы абзацев государства

  • Григорий (папа Григорий XIII) упал 10 дней, чтобы привести календарь обратно в синхронизации с сезонами. Соответственно, когда новый календарь был использован, ошибка, накопленная за 13 столетий, поскольку Никейский совет был исправлен путем удаления десяти дней. Юлианский календарь день четверг, 4 Октябрь 1582 последовали первый день по григорианскому календарю, Пятница, 15 Октябрь 1582 (цикл будняма был не влияет). *

В сущности, сроки от 5 октября 1582 года по 14 октября 1582 года в Григорианском календаре не существует. Я подозреваю, что .Net Framework использует обобщенную формулу и не учитывает разницу при работе с датами до 15 октября 1582 года, тогда как библиотека Java учитывает это.

+0

+1 Спасибо, что нашли время, чтобы добавить объяснение. Я знал о дыре и предполагал, что это общеизвестно. Тем не менее, мой вопрос был не «почему дыра?», А скорее «почему НЕ отверстие в .NET« DateTime »?» - Угадайте, почему историческая сторона не была покрыта до сих пор. –

+0

О, и кстати, этот материал * увлекательный *! –

 Смежные вопросы

  • Нет связанных вопросов^_^