Can I translate .net assembly versions to dates?
All of my .NET assemblies uses the 1.0.* format for t开发者_如何学编程heir version numbers. Supposedly the * gets replaced with the current date and time, translated into a number. What is the formula to translate it back into a date and time?
The AssemblyVersionAttribute
documentation states that:
The default build number increments daily. The default revision number is the number of seconds since midnight local time (without taking into account time zone adjustments for daylight saving time), divided by 2.
The reference date for the build number isn't specified. In practice, I've found this to be 1 January 2000.
The date can therefore be reconstructed as follows:
var result = new DateTime(2000, 1, 1);
result = result.AddDays(buildNumber);
result = result.AddSeconds(revision * 2);
Since the reference date isn't documented, it can't be guaranteed to always remain unchanged.
In Roslyn and .NET Core, the compiler source code is now available.
The file roslyn/src/Compilers/Core/Portable/VersionHelper.cs
( https://github.com/dotnet/roslyn/blob/614299ff83da9959fa07131c6d0ffbc58873b6ae/src/Compilers/Core/Portable/VersionHelper.cs - from commit 4f44984 on 2016-04-19 ) does have the same date logic from the original csc
in the method GenerateVersionFromPatternAndCurrentTime
:
int revision = (int)time.TimeOfDay.TotalSeconds / 2;
// 24 * 60 * 60 / 2 = 43200 < 65535
Debug.Assert(revision < ushort.MaxValue);
// ...
TimeSpan days = time.Date - new DateTime(2000, 1, 1);
int build = Math.Min(ushort.MaxValue, (int)days.TotalDays);
return new Version(pattern.Major, pattern.Minor, (ushort)build, (ushort)revision);
However the documentation comments simply say "a time-based value" without being specific about how it's generated.
But indeed, so far the Build
is still days since 2000-01-01 and Revision
is half the number of seconds since midnight.
Interestingly, this behavior is defined and verified in the test cases in VersionHelperTests.cs
: https://github.com/dotnet/roslyn/blob/614299ff83da9959fa07131c6d0ffbc58873b6ae/src/Compilers/Core/CodeAnalysisTest/VersionHelperTests.cs
The version string has this format:
<major version>.<minor version>.<build number>.<revision>
and if you set the version as you've described, to 1.0.*
:
The result of this is a build number set to the number of days since a random, designated start date and the revision based on the number of seconds since midnight.
The key here is "random". So, you can translate the revision to a time of day, but it sounds like you won't be able to resolve it to a date.
http://msdn.microsoft.com/en-us/library/ms998223.aspx
According to MSDN: "The default build number increments daily. The default revision number is random."
If you look at the source for AssemblyVersionAttribute
in reflector, you will see it's not doing anything at all, just accepting the string. So the magic happens with the compiler itself, which as far as I can tell is not documented anywhere. "Incremented everyday" is pretty vague, starting from what point?
I wouldn't expect to be able to use these versions with any reliability. It is probably better to base your version off of a label in a source control system or something like that.
The assembly versioning is documented here: http://msdn.microsoft.com/en-us/library/51ket42z.aspx
From the quote below, I would say that what you're asking is not possible and your information is incorrect.
Assembly Version Number Each assembly has a version number as part of its identity. As such, two assemblies that differ by version number are considered by the runtime to be completely different assemblies. This version number is physically represented as a four-part string with the following format:
<major version>.<minor version>.<build> number>.<revision>
However, at the bottom of the page I linked to, there is information about custom assembly attributes and a link to setting assembly attributes. You may find something helpful there. Edit - added
I took a look at the link you posted in your answer to my comment, and the only thing I see is this:
The result of this is a build number set to the number of days since a random, designated start date and the revision based on the number of seconds since midnight.
Based on the fact that it says a "random designated start date" I would say that wha you're asking is probably possible if you can figure out what the random designated start date is, but I doubt it would be worth the effort to find out.
shameless plug for coding best pactices
You'd be better served to be using revision control and an automated build process and use the logs from those to determine an asembly's build date.
Even if you could calculate the date/time from the auto-generated build number, I wouldn't recommend it. The build number wasn't meant for that purpose. It was simply meant to be an auto-generated value you can depend on to continually increase. No further logic should be assumed by a consuming application. If you want a fragment of the version number to include a date/time stamp, then you should integrate that logic into your build process / scripts / however else you may choose to do so.
I use a PostBuild script on my assemblies calling UpdateVersion on the AssemblyInfo.cs
We use the following format for versions |Year|Month|Day|BuildCounter|.
As the update version is open source, you can modify it to suit.
I've modified it to use the current date and a counter that is increased each build.
This way the version number always changes, and I can derive the date from the version number.
Very handy indeed.
Old post but hopefully this will provide another (easy) option for updating version number on build. I used a MSBUILD RegexTransform step to modify the version numbers. Here is a post I frequently go back to when I need to implement this feature.
http://weblogs.asp.net/srkirkland/archive/2010/12/07/simple-msbuild-configuration-updating-assemblies-with-a-version-number.aspx
Basically, in your MSBUILD proj file you create a transform on your AssemblyInfo file. Something like:
<ItemGroup>
<RegexTransform Include="$(SolutionRoot)\CommonAssemblyInfo.cs">
<Find>(?<major>\d+)\.(?<minor>\d+)\.\d+\.(?<revision>\d+)</Find>
<ReplaceWith>$(BUILD_NUMBER)</ReplaceWith>
</RegexTransform>
</ItemGroup>
where BUILD_NUMBER is supplied externally:
msbuild myBuild.proj /p:Configuration="%config%" /p:build_number="%version%"
/* Use this method */
/// <summary>
/// Gets the Assembly build date in string format
/// </summary>
/// <param name="assemblyVersion"></param>
/// <param name="dateFormat"></param>
/// <returns></returns>
private static string GetAssemblyBuildDate(string assemblyVersion,string dateFormat = "")
{
DateTime buildDate = new DateTime(2000, 1, 1);
Version currentAssemblyVersion = Version.Parse(assemblyVersion);
buildDate = buildDate.AddDays(currentAssemblyVersion.Build);
buildDate = buildDate.AddSeconds(currentAssemblyVersion.Revision * 2);
return string.IsNullOrEmpty(dateFormat) == false ? buildDate.ToString(dateFormat) : buildDate.ToString();
}
精彩评论