Bug 15217 - TimeDateStamp of PE COFF Assembly header is UTC, VS2012 uses Localtime
Summary: TimeDateStamp of PE COFF Assembly header is UTC, VS2012 uses Localtime
Alias: None
Product: Compilers
Classification: Mono
Component: Other ()
Version: 3.2.x
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2013-10-04 17:43 UTC by Cameron
Modified: 2013-10-04 21:50 UTC (History)
1 user (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Cameron 2013-10-04 17:43:20 UTC
Mono writes a UTC link/build time in its PE headers of output assemblies.
Microsoft(VS2012) writes a local time in its PE headers of output assemblies.

So, if, from Seattle[UTC-8] you compile test.cs into mono.exe and vs2012.exe using Mono and VS2012 respectivly,
the timestamps in the PE header will be 8 hours apart.

It seems like mono might want to consider using consistent behavior as VS2012, even if not as nice as having UTC timestamsp.
[it is true, you then need to know where the assembly was compiled to get a UTC buildtime, but hey...]

Code from here: http://stackoverflow.com/a/1600990/86375 and Linqpad can be used to dump the header datetimes, and view the problem.

A full linqpad program solution for testing is here:

void Main()
	DateTime a;
	a = RetrieveLinkerTimestamp(System.Reflection.Assembly.GetCallingAssembly().Location);
	Console.WriteLine ("{0}   DateTimeKind = {1}",a,a.Kind);
	a = RetrieveLinkerTimestamp(@"mono.exe");
	Console.WriteLine ("{0}   DateTimeKind = {1}",a,a.Kind);
	a = RetrieveLinkerTimestamp(@"vs2012.exe");
	Console.WriteLine ("{0}   DateTimeKind = {1}",a,a.Kind);

// Define other methods and classes here
private DateTime RetrieveLinkerTimestamp( string filePath)

	    const int c_PeHeaderOffset = 60;
	    const int c_LinkerTimestampOffset = 8;
	    byte[] b = new byte[2048];
	    System.IO.Stream s = null;
	        s = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
	        s.Read(b, 0, 2048);
	        if (s != null)
	    int i = System.BitConverter.ToInt32(b, c_PeHeaderOffset);
	    int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);
	    DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
	    dt = dt.AddSeconds(secondsSince1970);

		// This is appropriate for Mono assemblies, but not VS2012 assemblies
		//	dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
	    return dt;
Comment 1 Cameron 2013-10-04 21:50:49 UTC
Turns out I misidentified the source of my messed up timestamps.