C # Получить конкретную дату в ToInt64 (миллисекунды) - PullRequest
0 голосов
/ 02 июля 2018

Я просто не могу понять это ... Черт! Пожалуйста, посмотрите метод вызова во втором фрагменте кода. Вы увидите закомментированную строку, которая гласит // _ time = time.ToUTCString (); Перейдите к первому фрагменту кода, чтобы увидеть метод ToUTCString () . Вы можете видеть, что он принимает дату и время, преобразует его в универсальное время и вычитает UnixEpoch, чтобы получить TotalSeconds. Затем он преобразует это значение в Int64 () и, наконец, в строку. Я пытался вызвать метод ToLocalString, но это также меняет дату.

Дата, которую я передаю, является датой, которую я хочу преобразовать в Int64 и, в конечном итоге, в строку. Дата и время прохождения. Не изменено.

Я не хочу менять указанную дату. Я всегда передаю дату, начинающуюся с 12:00:00 (или 00:00:00), и это время, которое я всегда хочу. Оба эти метода изменяют дату и / или время . Дата, которую я передаю, - 06/01/2017 12:00:00 AM, но иногда она изменяется на 05/31/2017 04: 00: 00 или она сохраняет дату, но время не подходит Dark Sky требует, чтобы дата была значением Convert.ToInt64 (миллисекунды) и затем преобразовывалась в строку.

Кто-нибудь знает, как получить точную дату и время, преобразованные в Int64, с использованием миллисекунд?

У меня есть следующий класс расширений:

public static class Extensions
{
    private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static DateTime ToDateTime(this Int64 _input)
    {
        return UnixEpoch.AddSeconds(_input);
    }

    public static string ToLocalString(this DateTime _input)
    {
        // _input = {6/1/2017 12:00:00 AM}  System.DateTime
        var milliseconds = _input.ToLocalTime().Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(milliseconds).ToString();
        // I want to get the milliseconds for {6/1/2017 12:00:00 AM}
        // I don't want the date or time to change
    }

    public static string ToUTCString(this DateTime _input)
    {
        // _input = {6/1/2017 12:00:00 AM}  System.DateTime
        var milliseconds = _input.ToUniversalTime().Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(milliseconds).ToString();
        // I want to get the milliseconds for {6/1/2017 12:00:00 AM}
        // I don't want the date or time to change
    }
}

Это метод вызова:

    public ForecastIORequest(string apiKey, float latF, float longF, DateTime time, Unit unit, Language? lang = null, Extend[] extend = null, Exclude[] exclude = null)
    {
        _apiKey      = apiKey;
        _latitude    = latF.ToString(CultureInfo.InvariantCulture);
        _longitude   = longF.ToString(CultureInfo.InvariantCulture);
        //_time      = time.ToUTCString();
        _time        = time.ToLocalString();
        //DateTime t = _time.
        _unit        = Enum.GetName(typeof(Unit), unit);
        _extend      = (extend != null) ? RequestHelpers.FormatExtendString(extend) : "";
        _exclude     = (exclude != null) ? RequestHelpers.FormatExcludeString(exclude) : "";
        _lang        = (lang != null) ? RequestHelpers.FormatLanguageEnum(lang) : Language.en.ToString();
    }

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Есть фундаментальная проблема с тем, как вы обрабатываете даты здесь, и если я сведу это к одной вещи, я думаю, проблема в том, что ToUniversalTime() не работает так, как вы думаете.

То, что ToUniversalTime() делает, просто дает UTC время, определенное в другом часовом поясе. Например, скажем, мое местное время - UTC-7. Поэтому, если я определяю DateTime объект без указания DateTimeKind и устанавливаю значение, скажем, 2017/6/1 9:00:00, это означает, что в то время фактическое UTC время будет 2017/6/1 16:00:00 при этом время, и ToUniversalTime() даст вам DateTime объект с этим значением.

Позвольте мне немного изменить ваш ToUTCString() метод и показать вам проблему с ним. Теперь он возвращает long вместо string, и я разбиваю первую строку кода на две.

public static long ToUTC(this DateTime _input)
{
    var utcTime = _input.ToUniversalTime();
    var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
    return Convert.ToInt64(totalSeconds);
}

И обратите внимание, что в вашем Extensions классе объект UnixEpoch DateTimeKind установлен на UTC. Я изменил дату на 2017/6/1 8:00:00 для простоты понимания.

private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);

public static DateTime ToDateTime(this Int64 _input)
{
    return UnixEpoch.AddSeconds(_input);
}

Теперь давайте вызовем этот метод с DateTime объектом, для которого DateTimeKind имеет значение UTC.

// dateObj will have time 2017/6/1 9:00:00 _in UTC_.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
// This method converts to UTC, but it's already in UTC, so no actual conversion takes place.
// Then subtracts UnixEpoch from it, which is also in UTC. 
long dateInLong = dateObj.ToUTC();
// The difference is one hour, so dateInLong will be 3600.
Console.WriteLine(dateInLong);
// This method adds the above difference to UnixEpoch, and displays the time.
Console.WriteLine(dateInLong.ToDateTime());

Теперь здесь все в UTC, и вы должны увидеть результат, как и ожидалось, как показано ниже:

3600

6/1/2017 09: 00: 00

Пока все хорошо.

Теперь немного изменим ситуацию, и давайте установим наш dateObj на локальный вместо UTC, как вы делаете в своем примере.

// Notice that the object is in local time now.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());

Теперь у вышеупомянутого dateObj будет время 9:00:00, , но в моем местном времени . Мое фактическое местоположение - UTC-7, поэтому обратите внимание, что для меня это означает 9AM по местному времени 4PM UTC. Но обратите внимание, что мы не изменили объект UnixEpoch, который все еще находится в UTC, и в нем установлено время 8AM UTC. И, следовательно, dateInLong будет 28,800 (8 часов x 60 минут x 60 секунд). Поэтому, когда вызывается ваш метод ToDateTime(), он добавляет 28,000 секунд к 8AM UTC времени и возвращает как DateTime объект, время которого сейчас равно 4PM UTC.

28800

6/1/2017 16: 00: 00

И именно поэтому в зависимости от времени, которое вы установили для dateObj, ваш выходной сигнал меняет время, как вы сказали.


Решение

Вам нужно решить, какой часовой пояс использовать, и придерживаться этого. Один из вариантов - избавиться от всех преобразований UTC и установить время по местному времени.

public static class Extensions
{
    // NOT set to UTC
    private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0);

    public static DateTime ToDateTime(this Int64 _input)
    {
        return UnixEpoch.AddSeconds(_input);
    }

    public static long ToUTC(this DateTime _input)
    {
        // NOT converted to UTC. So... change variable names accordingly.
        var utcTime = _input;
        var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(totalSeconds);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Notice that the object is in local time and NOT UTC.
        var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
        long dateInLong = dateObj.ToUTC();
        Console.WriteLine(dateInLong);
        Console.WriteLine(dateInLong.ToDateTime());
        Console.ReadLine();
    }
}

Другой вариант - установить для ВСЕГО значение UTC, но тогда вам необходимо убедиться, что объект DateTime, для которого вы вызываете ToUTC(), определен в UTC, а не локально.

Итак:

private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);

И

var utcTime = _input.ToUniversalTime();

И, наконец,

var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);

НО ...

Я вижу большую проблему с вашим кодом, глядя на второй фрагмент кода. В конструкторе ForecastIORequest() вы экономите время как string. И это не идеальное решение, на мой взгляд. Потому что, поскольку вы нашли трудный путь, в зависимости от того, в каком часовом поясе был создан вызывающий объект, ваша разница во времени будет, ну, в общем, разной. И ты не сможешь узнать, что именно.

Я бы предпочел сохранить объект DateTime в том виде, как он есть, прочитать его и вычислить разницу при необходимости с учетом часовых поясов.

Надеюсь, это поможет.

0 голосов
/ 02 июля 2018

См. DateTime.Ticks - в миллисекунде 10 000 тиков. Просто возьмите DateTime.Ticks / 10000 (десять тысяч), и у вас есть миллисекунды.

Вот простой метод расширения для получения длинных миллисекунд (это Int64):

public static long ToMilliseconds(this DateTime dateTime)
{
    return dateTime.Ticks / 10000;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...