Создание номера ревизии из даты / времени - PullRequest
0 голосов
/ 06 октября 2009

Есть ли альтернатива номеру ревизии (увеличенный int)? Я хотел бы создать тег ревизии (или идентификатор, если хотите) из даты + времени (а затем преобразовать тег обратно в объект даты и времени).

Желательно, чтобы ревизия была как можно меньше. CouchDB использует такой формат для ревизии: 765B7D1C - но я не уверен, как они это сделали, и даже если это даже отметка времени.

Есть предложения?

Ответы [ 5 ]

1 голос
/ 06 октября 2009

Вы можете использовать что-то вроде этого:

DateTime.Now.Subtract(new DateTime(2000, 1, 1)).Days

Возвращает количество дней с 2000-01-01 (на сегодняшний день это будет 3566).

Это похоже на то, что используется в .NET, если указать версию сборки (в AssemblyInfo.cs) как "1.0. *". Конечно, вы также можете использовать другую дату начала, например, начало вашего проекта.

0 голосов
/ 08 ноября 2016

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

Представьте себе дату и время 2016-11-08 14:08:12. Это уже строковая кодировка из 19 символов (19 байт, если строка, а не wstring).

Строка: Мне нравится yyyyMMdd-HHmmss: 20161108-140812. 15 символов. Я думаю, что это больше человек, читаемый без черточек и двоеточий.

BCD: Int64 хранит 16 десятичных цифр всего в 8 байтах, сохраняя удобочитаемость для человека (если смотреть как шестнадцатеричный). Выбор:
0x0020161108140812 (годы 0-799,999; разрешение 1с)
0x0201611081408120 (годы 0-79,999; разрешение 0,1 с)
0x2016110814081200 (годы 0-7999; разрешение 0,01 с)
(Первая цифра ограничена 0,7, потому что Int64 подписан; его максимальное значение 0x7fffffffffffffff.)

Десятичное число: Int64 хранит 18,96 десятичных цифр только в 8 байтах. 0000020161108140812 (годы 0-922,337,203; разрешение 1с)
0020161108140812000 (годы 0-922,337; разрешение 0,001 с)
(максимальное значение - 9 223 372 036 854 775 807).

UInt32 может хранить дату (8 цифр) в формате BCD или десятичной.
0x20161108 (годы 0-9999 или 15,999)
0020161108 (годы 0-429,496)

Int32 может хранить дату как BCD или десятичное число.
0x20161108 (годы 0-7999)
0020161108 (годы 0-214,748)

Возможности почти безграничны (если вы не смотрите на стандарт).

Это лишь некоторые из наиболее читаемых человеком вариантов.

0 голосов
/ 08 ноября 2016

Задача такова: можете ли вы дата + время компиляции скомпилировать в вашу программу? Предпочтительно в выбранном вами формате, но достаточно любого формата, потому что вы можете переформатировать в «тег» любым удобным вам способом. (Если вы не можете переформатировать его во время компиляции, вы можете переформатировать его до неузнаваемости во время выполнения.)

Ответ таков: прямого пути нет. C # не имеет ничего общего с __DATE__ или __TIME__. Дата + время компиляции полностью недоступно во время компиляции. Если программа хочет знать дату + время ее компиляции, она может только попытаться подобрать их во время выполнения, , изучив себя . C # создает структуры данных внутри и вокруг скомпилированной программы, но ни одно из полей не доступно во время компиляции, и ни одно из них не гарантирует дату + время компиляции.

Решение 1 (мое любимое на данный момент): VS не безоговорочно записывает дату + время компиляции в поля с соответствующим названием, чтобы предоставить вам эту информацию. Но он условно записывает производную даты + времени компиляции в 2 из 4 полей версии, в качестве хитрого способа поставить автоматически увеличивающийся номер версии в исполняемый файл, если вы скажете это. AssemblyVersion - это структура из 4 полей («Major Version», «Minor Version», «Build Number» и «Revision»), которые обычно представляют собой всего лишь 4 номера UInt16, введенные программистом (или программой контроля версий). Но, Если установить поля AssemblyVersion равными a, b, * и [пустая строка], , и никто не изменит последние 2 , тогда компилятор заменяет последние два на c и d, где c == дни и d * 2 == секунды с 1 января 2000 года в 00:00 (по местному времени, но без учета перехода на летнее время) (без -human-decodable timestamp (отображается в разделе «Свойства файла» файла), в данный момент она анализирует AssemblyInfo.cs. К ним легко получить доступ через:

private string DateCompiled()
{
    System.Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
    // v.Build == days and v.Revision*2 == seconds since Jan. 1, 2000 at 00:00 (midnight, 12:00am). (Local time, but disregards daylight saving time.)
    return new DateTime(2000, 1, 1).AddDays(v.Build).AddSeconds(v.Revision * 2).ToString("yyyyMMdd-HHmm (local no DST)");

    // "Assembly version" has four UInt16 fields: "Major Version", "Minor Version", "Build Number", and "Revision".
    // When Build is "*" and Revision is empty, the compiler overrides them with the encoded date and time.
    // AssemblyVersion can be specified in the solution Properties window, Application tab, "Assembly Information..." button and dialog box: Assembly version.
    // AssemblyVersion can also be specified in "AssemblyInfo.cs". Example:
    //   [assembly: AssemblyVersion("2016.11.*")]
    // AssemblyFileVersion is optional, defaulting to AssemblyVersion if not specified. (Build is NOT allowed to be "*".)
    // Properties of the file (in Windows Explorer) displays AssemblyFileVersion.
    // AssemblyVersion can be specified in the solution Properties window, Application tab, "Assembly Information..." button and dialog box: File version.
    // AssemblyVersion can also be specified in "AssemblyInfo.cs". Example:
    //   [assembly: AssemblyFileVersion("1.2.3.4")]
}

Если вы хотите, чтобы File: Properties (в Internet Explorer) отображала произвольную версию a.b.c.d по вашему выбору, вы можете сделать это тоже. Файл: Свойства показывает AssemblyFileVersion, который по умолчанию равен AssemblyVersion, если не указан. Вы можете указать только AssemblyFileVersion в "AssemblyInfo.cs" (просто добавьте для него новую строку, используя тот же синтаксис, что и AssemblyVersion, за исключением того, что "*" не допускается). Использование [половины] AssemblyVersion для закодированной даты + времени компиляции скрыто от этого представления.

Решение 2: (Мне это не нравится, потому что метаданные легко изменяются, и доступ может быть заблокирован.) Работающая программа находит себя (файл .exe) через файловую систему и считывает свою собственную дату последнего изменения. Но последняя измененная дата - это метаданные, хранящиеся в файловой системе, а не файл программы. Дата последнего изменения может быть легко изменена или утеряна путем переноса между часовыми поясами или изменениями летнего времени через FAT, CDFS или FTP; ленивые FTP-серверы, которые не принимают входящие метаданные дата + время; безумные FTP-серверы, которые округляют старые отметки времени; и файловые утилиты, которые изменяют метаданные по запросу. И иногда права доступа к файлам мешают. И необходимая процедура зависит от операционной системы. (Даже если бы я попробовал этот подход, я бы не вставлял код)

Решение 3: (Я считаю, что это лучше, чем Решение 2, потому что данные не могут измениться, но хуже, чем Решение 2, потому что исполняемый файл открывается и считывает себя как двоичные данные.) "Дастин Алексюк недавно опубликовал умная запись в блоге, описывающая, как извлечь временную метку встроенного компоновщика из раздела IMAGE_FILE_HEADER заголовка Portable Executable "- https://blog.codinghorror.com/determining-build-date-the-hard-way/ (с кодом). Запись в блоге (с 3 марта 2005 г.), на которую он ссылается, исчезла (вместе со всем блогом), но она заархивирована в http://web.archive.org/web/20060615040705/http://blog.signaleleven.com/index.php?itemid=10

0 голосов
/ 06 октября 2009

Взгляните на VSVersion Manager , который представляет собой набор макросов для установки номеров версий в AssemblyInfo на основе даты.

Макрос запускается при каждой сборке.

Вы можете установить правила для установки полей редакции для любого из элементов даты (месяц, день, год в разных форматах), увеличивать их на единицу или оставить без изменений.

Сайт содержит подробные инструкции по установке макросов.

0 голосов
/ 06 октября 2009

Я недавно прошел через тот же мыслительный процесс. Я не мог найти хороший способ вписать его в подписанный int, который вы позволили. Вместо этого я пошел с майором. {Год-2000}. {MMdd}. {SVN Revision}. Вы все еще могли бы попытаться напихать дату ... вот проблема:

1 год = 365 дней = 8760 часов = 525600 минут. Как вы можете видеть, учитывая максимум 32 КБ, лучшее, что вы можете сделать в текущем году, это часы. Это может записать следующие 3,5 года, так что вы можете сделать:

int revision = (int) (DateTime.Now - new DateTime(2009, 1, 1)).TotalHours;

... и это произойдет примерно в августе 2012 года. Или, если вы будете использовать дни, вы сможете хранить приблизительно 88 лет, так что вы можете спокойно следовать совету Мартина.

...