|  | @@ -3,6 +3,7 @@ using System.Collections.Generic;
 | 
	
		
			
				|  |  |  using System.Linq;
 | 
	
		
			
				|  |  |  using System.Globalization;
 | 
	
		
			
				|  |  |  using Renci.SshNet.Common;
 | 
	
		
			
				|  |  | +using System.Diagnostics;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -11,7 +12,7 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |      /// </summary>
 | 
	
		
			
				|  |  |      public class SftpFileAttributes
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        #region Bitmask constats
 | 
	
		
			
				|  |  | +        #region Bitmask constants
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          private const uint S_IFMT = 0xF000; //  bitmask for the file type bitfields
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -60,8 +61,8 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |          private bool _isGroupIDBitSet;
 | 
	
		
			
				|  |  |          private bool _isStickyBitSet;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        private readonly DateTime _originalLastAccessTime;
 | 
	
		
			
				|  |  | -        private readonly DateTime _originalLastWriteTime;
 | 
	
		
			
				|  |  | +        private readonly DateTime _originalLastAccessTimeUtc;
 | 
	
		
			
				|  |  | +        private readonly DateTime _originalLastWriteTimeUtc;
 | 
	
		
			
				|  |  |          private readonly long _originalSize;
 | 
	
		
			
				|  |  |          private readonly int _originalUserId;
 | 
	
		
			
				|  |  |          private readonly int _originalGroupId;
 | 
	
	
		
			
				|  | @@ -70,12 +71,12 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          internal bool IsLastAccessTimeChanged
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            get { return _originalLastAccessTime != LastAccessTime; }
 | 
	
		
			
				|  |  | +            get { return _originalLastAccessTimeUtc != LastAccessTimeUtc; }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          internal bool IsLastWriteTimeChanged
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            get { return _originalLastWriteTime != LastWriteTime; }
 | 
	
		
			
				|  |  | +            get { return _originalLastWriteTimeUtc != LastWriteTimeUtc; }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          internal bool IsSizeChanged
 | 
	
	
		
			
				|  | @@ -104,20 +105,58 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets or sets the time the current file or directory was last accessed.
 | 
	
		
			
				|  |  | +        /// Gets or sets the local time the current file or directory was last accessed.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          /// <value>
 | 
	
		
			
				|  |  | -        /// The time that the current file or directory was last accessed.
 | 
	
		
			
				|  |  | +        /// The local time that the current file or directory was last accessed.
 | 
	
		
			
				|  |  |          /// </value>
 | 
	
		
			
				|  |  | -        public DateTime LastAccessTime { get; set; }
 | 
	
		
			
				|  |  | +        public DateTime LastAccessTime
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            get
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return ToLocalTime(this.LastAccessTimeUtc);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            set
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                this.LastAccessTimeUtc = ToUniversalTime(value);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets or sets the local time when the current file or directory was last written to.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <value>
 | 
	
		
			
				|  |  | +        /// The local time the current file was last written.
 | 
	
		
			
				|  |  | +        /// </value>
 | 
	
		
			
				|  |  | +        public DateTime LastWriteTime
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            get
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return ToLocalTime(this.LastWriteTimeUtc);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            set
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                this.LastWriteTimeUtc = ToUniversalTime(value);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets or sets the UTC time the current file or directory was last accessed.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <value>
 | 
	
		
			
				|  |  | +        /// The UTC time that the current file or directory was last accessed.
 | 
	
		
			
				|  |  | +        /// </value>
 | 
	
		
			
				|  |  | +        public DateTime LastAccessTimeUtc { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  | -        /// Gets or sets the time when the current file or directory was last written to.
 | 
	
		
			
				|  |  | +        /// Gets or sets the UTC time when the current file or directory was last written to.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          /// <value>
 | 
	
		
			
				|  |  | -        /// The time the current file was last written.
 | 
	
		
			
				|  |  | +        /// The UTC time the current file was last written.
 | 
	
		
			
				|  |  |          /// </value>
 | 
	
		
			
				|  |  | -        public DateTime LastWriteTime { get; set; }
 | 
	
		
			
				|  |  | +        public DateTime LastWriteTimeUtc { get; set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets or sets the size, in bytes, of the current file.
 | 
	
	
		
			
				|  | @@ -395,10 +434,10 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        internal SftpFileAttributes(DateTime lastAccessTime, DateTime lastWriteTime, long size, int userId, int groupId, uint permissions, IDictionary<string, string> extensions)
 | 
	
		
			
				|  |  | +        internal SftpFileAttributes(DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc, long size, int userId, int groupId, uint permissions, IDictionary<string, string> extensions)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            LastAccessTime = _originalLastAccessTime = lastAccessTime;
 | 
	
		
			
				|  |  | -            LastWriteTime = _originalLastWriteTime = lastWriteTime;
 | 
	
		
			
				|  |  | +            LastAccessTimeUtc = _originalLastAccessTimeUtc = lastAccessTimeUtc;
 | 
	
		
			
				|  |  | +            LastWriteTimeUtc = _originalLastWriteTimeUtc = lastWriteTimeUtc;
 | 
	
		
			
				|  |  |              Size = _originalSize = size;
 | 
	
		
			
				|  |  |              UserId = _originalUserId = userId;
 | 
	
		
			
				|  |  |              GroupId = _originalGroupId = groupId;
 | 
	
	
		
			
				|  | @@ -491,9 +530,9 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (IsLastAccessTimeChanged || IsLastWriteTimeChanged)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                var time = (uint)(LastAccessTime.ToFileTime() / 10000000 - 11644473600);
 | 
	
		
			
				|  |  | +                var time = (uint)(LastAccessTimeUtc.ToFileTimeUtc() / 10000000 - 11644473600);
 | 
	
		
			
				|  |  |                  stream.Write(time);
 | 
	
		
			
				|  |  | -                time = (uint)(LastWriteTime.ToFileTime() / 10000000 - 11644473600);
 | 
	
		
			
				|  |  | +                time = (uint)(LastWriteTimeUtc.ToFileTimeUtc() / 10000000 - 11644473600);
 | 
	
		
			
				|  |  |                  stream.Write(time);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -521,8 +560,8 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |              var userId = -1;
 | 
	
		
			
				|  |  |              var groupId = -1;
 | 
	
		
			
				|  |  |              uint permissions = 0;
 | 
	
		
			
				|  |  | -            var accessTime = DateTime.MinValue;
 | 
	
		
			
				|  |  | -            var modifyTime = DateTime.MinValue;
 | 
	
		
			
				|  |  | +            DateTime accessTime;
 | 
	
		
			
				|  |  | +            DateTime modifyTime;
 | 
	
		
			
				|  |  |              IDictionary<string, string> extensions = null;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if ((flag & 0x00000001) == 0x00000001)   //  SSH_FILEXFER_ATTR_SIZE
 | 
	
	
		
			
				|  | @@ -544,10 +583,17 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if ((flag & 0x00000008) == 0x00000008)   //  SSH_FILEXFER_ATTR_ACMODTIME
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | +                // The incoming times are "Unix times", so they're already in UTC.  We need to preserve that
 | 
	
		
			
				|  |  | +                // to avoid losing information in a local time conversion during the "fall back" hour in DST.
 | 
	
		
			
				|  |  |                  var time = stream.ReadUInt32();
 | 
	
		
			
				|  |  | -                accessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
 | 
	
		
			
				|  |  | +                accessTime = DateTime.FromFileTimeUtc((time + 11644473600) * 10000000);
 | 
	
		
			
				|  |  |                  time = stream.ReadUInt32();
 | 
	
		
			
				|  |  | -                modifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
 | 
	
		
			
				|  |  | +                modifyTime = DateTime.FromFileTimeUtc((time + 11644473600) * 10000000);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                accessTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 | 
	
		
			
				|  |  | +                modifyTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if ((flag & 0x80000000) == 0x80000000)   //  SSH_FILEXFER_ATTR_EXTENDED
 | 
	
	
		
			
				|  | @@ -572,5 +618,37 @@ namespace Renci.SshNet.Sftp
 | 
	
		
			
				|  |  |                  return FromBytes(stream);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private static DateTime ToLocalTime(DateTime value)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            DateTime result;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (value == DateTime.MinValue)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                result = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Local);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                result = value.ToLocalTime();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private static DateTime ToUniversalTime(DateTime value)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            DateTime result;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (value == DateTime.MinValue)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                result = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                result = value.ToUniversalTime();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |