Как объявить свойство DateTime с правильным DateTimeKind?

#c# #datetime #timezone

#c# #datetime #Часовой пояс

Вопрос:

Я хочу иметь что-то вроде этого:

 [Kind=DateTimeKind.Utc]
public DateTime CreatedOn { get; set; }
  

Возможно ли таким образом декларативно задать вид? Что такое правильный синтаксис? У меня есть классы-заглушки для использования в моем веб-сервисе JSON WCF, и когда другой конец (клиент Java) получает даты — все они нравятся:

123456000-0500

Где «-0500» — это мой часовой пояс, и если я беру только левую часть, то это неправильная дата UTC (я должен вычесть 5 часов). Я бы предпочел исправить это на сервере.

Редактировать:

  1. Я сохраняю все даты в базе данных (SQL Server) как UTC. Я никогда не имею дело с локальными датами, за исключением случаев, когда это необходимо отобразить.

  2. У меня есть простой класс, который я передаю в качестве ответа в моем сервисе WCF — JSON. Когда я заполняю этот класс, я запрашиваю базу данных с помощью EF и присваиваю значения в этом классе.

  3. На клиенте, который является телефоном Android с Java — я использую библиотеку Gson для десериализации. Gson не может десериализовать формат WCF, поэтому я уже написал свой уродливый десериализатор следующим образом:

    открытый класс GsonDateDeserializer реализует JsonDeserializer { публичная десериализация даты (JsonElement json, тип typeOfT, контекст JsonDeserializationContext) вызывает исключение JsonParseException { Строка s = json.getAsString(); s = s.replace(«/Дата(«, «»); s = s.replace(«)/», «»»);

         //if there us no data passed in - that means NULL
        if (s.equals("")) return null;
    
        //If we got timezone info with this date - cut it off
        if (s.length() > 5 amp;amp; (s.indexOf("-") == s.length()-5 || s.indexOf(" ") == s.length()-5))
        {
            s = s.substring(0, s.length()-5);
        }
    
        Long l = Long.valueOf(s);
    
        return new Date(l);
    
    }
      

    }

Я думал, что WCF передает «-0500» только для информации, чтобы клиент знал, в какой часовой пояс его следует преобразовать. Но нет. Оно передает левое число с добавлением 5 часов. Итак, я не хочу, чтобы сервер был «умным», а просто хочу, чтобы он передавал все даты как «-0000»

Комментарии:

1. вы хотите показать скорректированное время на сервере или на клиенте?

2. Я хочу, чтобы клиент получил 123456000-0000 — Я не хочу, чтобы WCF принимал мою дату UTC (которую я получаю из базы данных) и передавал ее как локальную

Ответ №1:

Что ж, эта дата соответствует правильному ISO 8601, поэтому другой конец должен ее принять. Если вы не можете это изменить или не хотите, вы можете сделать следующее:

 private DateTime m_createdOn;
public DateTime CreatedOn
{
    get { return m_createdOn; }
    set { m_createdOn = value.ToUniversalTime(); }
}
  

РЕДАКТИРОВАТЬ: Вы имеете в виду, что дата с часовым поясом неверна? В этом случае вам, вероятно, следует разрешить вашему уровню базы данных создавать даты с правильным DateKind .

Комментарии:

1. Смотрите мою ПРАВКУ в основном сообщении. И как мне сообщить SQL Server, что это за тип? Это просто DateTime, и я всегда сохраняю там даты UTC.

Ответ №2:

В итоге я завершил свою собственную функцию. Теперь при десериализации я учитываю часть часового пояса.

 public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
    {
        String s = json.getAsString().replace("/Date(", "").replace(")/", "");

        //if there us no data passed in - that means NULL
        if (s.equals("")) return null;

        //If we got timezone info handle separately:
        long offset = 0;
        if (s.length() > 5 amp;amp; (s.indexOf("-") == s.length()-5 || s.indexOf(" ") == s.length()-5))
        {
            //get offset minutes
            offset = Long.valueOf(s.substring(s.length()-4, s.length()-2))*60   Long.valueOf(s.substring(s.length()-2, s.length()));
            //Apply direction
            if (s.indexOf("-") == s.length()-5) offset = -offset;

            //Cutoff offset
            s = s.substring(0, s.length()-5);
        }

        return new Date(Long.valueOf(s)   offset * 60 * 1000);

    }