zoukankan      html  css  js  c++  java
  • 聊聊.netcore采坑那一些事之系统时间and文件路径

    聊聊.netcore采坑那一些事之系统时间and文件路径

    Hi,小伙伴大家好,最近工作比较忙,很久没有和大家分享点东西了。这个周末都加了两天班。公司的新项目都是采用.netcore来开发,在开发过程中,也踩到了一些坑,在此先总结两个坑,这两个坑都是关于Linux(CentOS)和windows下的兼容性问题。我们最开始的开发环境接口调用一直是部署在windows环境运行一切正常,但是部署到Linux(CentOS)环境下,就出现了这两个问题,其实问题也简单:获取系统时间,实际时间少了8个小时;文件路径​被识别为了文件名。下面就简单分享一下解决方式,其实只要你一看,发现很简单的,之所以分享出来,当你才开始用户.netcore时,可以有一个提示作用,嘿嘿!

     

    一、DateTime.Now获取系统时间少了8个小时

    .net core项目,部署到LinuxCentOS)上的时候,发现DateTime.Now获取的时间与Windows不一致,获取到系统时间比系统的时间实际少了8个小时,发现这一个问题,大家第一时间想到的是时区差异。网上搜了一下,发现还有不少的小伙伴遇到了同样的问题,有给出了对应的解决方式,具体如下:

    具体原因就是:Linux和Windows两者所采用的时区不同,两者的时区分别为:Linux:IANAWindows:Windows time zone IDs。这就是最终元凶啦!

    找到原因后,那么该如何解决呢?方式很简单,就是两者采用同一个时区不就完事了嘛,最终统一采用IANA,在实现上可以借助第三方库:NodaTime。具体实现代码如下:

           

     /// <summary>
    
            /// 获取系统当前时间
    
            /// </summary>
    
            /// <returns>系统当前时间</returns>
    
            public static DateTime GetSysDateTimeNow()
    
            {
    
                Instant now = SystemClock.Instance.GetCurrentInstant();
    
                var shanghaiZone = DateTimeZoneProviders.Tzdb["Asia/Shanghai"];
    
                return now.InZone(shanghaiZone).ToDateTimeUnspecified();
    
          }
    

      

    是不是so easy?

    其实我们使用时间的时候,会有很多种方式,也会对时间做很多格式转换,比如:yyyy-MM-dd HH:mm:ss格式化时间,时间和时间戳的相互转换等等。为了统一规范操作,在实际项目中,我们对时间的操作根据实际需要做了一个统一封装,当然了在很多人看来是没有多大技术含量的,也是哦,其目的是为了实现统一控制,方便管理,提高代码的复用性。现在我也把代码贴出,如果有需要的,你可以参考一下,同时我也生成了一个包,放到Nuget上,包名为(XYH.Tools.DateTimeTools),如果有需要的,可以挡下来使用。

    我已经将源码上传到GitHub上,有兴趣的可以档下来

    源码地址:https://github.com/xuyuanhong0902/XYH.Tools.git

    源码:

    /* ==============================================================================
     * 功能描述:所有时间的相关操作集合  
     * 创 建 者:程序修炼之旅 交流微信号:15908150902
     * 创建日期: 2020-03-08
     * CLR Version :1.0
     * ==============================================================================*/
    
    using NodaTime;
    using System;
    
    /// <summary>
    /// 公用帮助类
    /// </summary>
    namespace XYH.Tools.DateTimeTools
    {
        /// <summary>
        /// 时间相关的操作类
        /// </summary>
        public static class DateTimeTools
        {
            #region 获取系统当前时间的几个方法(返回时间+格式化后的时间字符串)
    
            /// <summary>
            /// 获取系统当前时间
            /// </summary>
            /// <returns>系统当前时间</returns>
            public static DateTime GetSysDateTimeNow()
            {
                Instant now = SystemClock.Instance.GetCurrentInstant();
                var shanghaiZone = DateTimeZoneProviders.Tzdb["Asia/Shanghai"];
                return now.InZone(shanghaiZone).ToDateTimeUnspecified();
            }
    
            /// <summary>
            /// 获取系统当前时间格式化字符串 24小时制 被格式化为 (yyyy-MM-dd HH:mm:ss.fff)
            /// </summary>
            /// <returns>系统当前格式化的时间字符串(yyyy-MM-dd HH:mm:ss.fff)</returns>
            public static string GetSysDateTimeNowStringYMD24HMSF()
            {
                return GetSysDateTimeNow().ToStringYMD24HMSF();
            }
    
            /// <summary>
            /// 获取系统当前时间格式化字符串 12小时制 被格式化为 (yyyy-MM-dd hh:mm:ss.fff)
            /// </summary>
            /// <returns>系统当前格式化的时间字符串(yyyy-MM-dd hh:mm:ss.fff)</returns>
            public static string GetSysDateTimeNowStringYMD12HMSF(this DateTime time)
            {
                return GetSysDateTimeNow().ToStringYMD12HMSF();
            }
    
            /// <summary>
            /// 获取系统当前时间格式化字符串 24小时制 被格式化为 (yyyy-MM-dd HH:mm:ss)
            /// </summary>
            /// <returns>系统当前格式化的时间字符串(yyyy-MM-dd HH:mm:ss)</returns>
            public static string GetSysDateTimeNowStringYMD24HMS(this DateTime time)
            {
                return GetSysDateTimeNow().ToStringYMD24HMS();
            }
    
            /// <summary>
            /// 获取系统当前时间格式化字符串 12小时制 被格式化为 (yyyy-MM-dd hh:mm:ss)
            /// </summary>
            /// <returns>系统当前格式化的时间字符串(yyyy-MM-dd hh:mm:ss)</returns>
            public static string GetSysDateTimeNowStringYMD12HMS(this DateTime time)
            {
                return GetSysDateTimeNow().ToStringYMD12HMS();
            }
    
            /// <summary>
            /// 获取系统当前时间格式化字符串  被格式化为 (yyyy-MM-dd)
            /// </summary>
            /// <returns>系统当前格式化的时间字符串(yyyy-MM-dd)</returns>
            public static string GetSysDateTimeNowStringYMD(this DateTime time)
            {
                return GetSysDateTimeNow().ToStringYMD();
            }
    
            #endregion
    
            #region DateTime 扩展几个 格式方法
    
            /// <summary>
            /// 时间 格式化 24小时制 被格式化为  (yyyy-MM-dd HH:mm:ss.fff)
            /// </summary>
            /// <param name="time">被格式的时间</param>
            /// <returns>格式化后的时间字符串(yyyy-MM-dd HH:mm:ss.fff)</returns>
            public static string ToStringYMD24HMSF(this DateTime time)
            {
                return time.ToString("yyyy-MM-dd HH:mm:ss.fff");
            }
    
            /// <summary>
            /// 时间 格式化 12小时制 被格式化为  (yyyy-MM-dd hh:mm:ss.fff)
            /// </summary>
            /// <param name="time">被格式化时间</param>
            /// <returns>格式化后的时间字符串(yyyy-MM-dd hh:mm:ss.fff)</returns>
            public static string ToStringYMD12HMSF(this DateTime time)
            {
                return time.ToString("yyyy-MM-dd hh:mm:ss.fff");
            }
    
            /// <summary>
            /// 时间 格式化 24小时制 被格式化为  (yyyy-MM-dd HH:mm:ss)
            /// </summary>
            /// <param name="time">被格式化时间</param>
            /// <returns>格式化后的时间字符串(yyyy-MM-dd HH:mm:ss)</returns>
            public static string ToStringYMD24HMS(this DateTime time)
            {
                return time.ToString("yyyy-MM-dd HH:mm:ss");
            }
    
            /// <summary>
            /// 时间 格式化 12小时制 被格式化为  (yyyy-MM-dd hh:mm:ss)
            /// </summary>
            /// <param name="time">被格式化时间</param>
            /// <returns>格式化后的时间字符串(yyyy-MM-dd hh:mm:ss)</returns>
            public static string ToStringYMD12HMS(this DateTime time)
            {
                return time.ToString("yyyy-MM-dd hh:mm:ss");
            }
    
            /// <summary>
            /// 时间 格式化  被格式化为  (yyyy-MM-dd)
            /// </summary>
            /// <param name="time">被格式化时间</param>
            /// <returns>格式化后的时间字符串(yyyy-MM-dd)</returns>
            public static string ToStringYMD(this DateTime time)
            {
                return time.ToString("yyyy-MM-dd");
            }
    
            #endregion
    
            #region 获取时间戳
    
            /// <summary>
            /// 获取时间戳(秒)
            /// </summary>
            /// <returns>秒时间戳</returns>
            public static long GetSecondTimestamp()
            {
                // 以1970-1-1 为时间开始 同系统当前时间的秒差值即为秒时间戳
                TimeSpan ts = GetSysDateTimeNow() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                return Convert.ToInt64(ts.TotalSeconds);
            }
    
            /// <summary>
            /// 获取时间戳(毫秒)
            /// </summary>
            /// <returns>毫秒时间戳</returns>
            public static long GetMilliSecondTimestamp()
            {
                // 以1970-1-1 为时间开始 同系统当前时间的毫秒差值即为毫秒时间戳
                TimeSpan ts = GetSysDateTimeNow() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                return Convert.ToInt64(ts.TotalMilliseconds);
            }
    
            #endregion
    
            #region 将一个时间戳转换为一个时间
    
            /// <summary>
            /// 将一个秒时间戳转换为时间格式(秒)
            /// </summary>
            /// <param name="secondTimestamp">秒时间戳</param>
            /// <returns>转换后的时间</returns>
            public static DateTime? SecondStampToDateTime(long secondTimestamp)
            {
                //  做一个简单的判断
                if (secondTimestamp <= 0)
                {
                    return null;
                }
    
                // 以1970-1-1 为时间开始,通过计算与之的时间差,来计算其对应的时间
                DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
                dateTime = dateTime.AddSeconds(secondTimestamp).ToLocalTime();
                return dateTime;
            }
    
            /// <summary>
            /// 将一个字符串秒时间戳转换为时间格式(秒)
            /// </summary>
            /// <param name="secondTimestampStr">字符串秒时间戳</param>
            /// <returns>转换后的时间</returns>
            public static DateTime? SecondStampToDateTime(string secondTimestampStr)
            {
                // 如果为空,那么直接返回null
                if (string.IsNullOrEmpty(secondTimestampStr))
                {
                    return null;
                }
    
                // 首先将字符串时间戳转换为数字
                long secondTimestamp = 0;
                long.TryParse(secondTimestampStr, out secondTimestamp);
    
                // 调用
                return SecondStampToDateTime(secondTimestamp);
            }
    
            /// <summary>
            /// 将一个字符串毫秒时间戳转换为时间格式(毫秒)
            /// </summary>
            /// <param name="secondTimestampStr">字符串毫秒时间戳</param>
            /// <returns>转换后的时间</returns>
            public static DateTime? MilliSecondStampToDateTime(long secondTimestamp)
            {
                //  做一个简单的判断
                if (secondTimestamp <= 0)
                {
                    return null;
                }
    
                // 以1970-1-1 为时间开始,通过计算与之的时间差,来计算其对应的时间
                DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
                dateTime = dateTime.AddMilliseconds(secondTimestamp).ToLocalTime();
    
                return dateTime;
            }
    
            /// <summary>
            /// 将一个毫秒时间戳转换为时间格式(毫秒)
            /// </summary>
            /// <param name="milliSecondStampStr">毫秒时间戳</param>
            /// <returns>转换后的时间</returns>
            public static DateTime? MilliSecondStampToDateTime(string milliSecondStampStr)
            {
                // 如果为空,那么直接返回null
                if (string.IsNullOrEmpty(milliSecondStampStr))
                {
                    return null;
                }
    
                // 首先将字符串时间戳转换为数字
                long milliSecondStamp = 0;
                long.TryParse(milliSecondStampStr, out milliSecondStamp);
    
                // 调用
                return MilliSecondStampToDateTime(milliSecondStamp);
            }
    
            #endregion
        }
    }
    

      

    二、文件路径被识别为了文件名

    哈哈,最近还遇到一个有趣的事情,就是在Windows上,文件路径的创建,都是正确的,但是部署到CentOS,所创建的文件,所有路径都变成了文件名称,所有文件都在根目录下了。

    网上找了一下原因,就是文件路径左斜杠和右斜杠的问题。在Windows上无论是左斜杠还是右斜杠都没有问题,但是在linux中只支持右斜杠,将代码中所用到的路径操作,都统一修改为右斜杠,问题就解决了。文件路径1/文件路径2/文件名

    三、总结

      回头来看这两个问题,都是系统的兼容性问题,在仔细想一下,也是一个习惯性问题,尤其是文件路径这问题,我们要习惯的用右斜杠。

    我们以后在写.net程序的时候,无论是否会采用.netcore实现linux系统部署,我们都也该想到不同系统的兼容性问题,在实现上都采用一个通用的方式来实现,那么以后在做项目升级,系统迁移的时候,就会少一些麻烦。嘿嘿,今天就先到这,后续我在分享一下其它.netcore实战所踩的坑。谢谢您的阅读。

    Hi,小伙伴大家好,最近工作比较忙,很久没有和大家分享点东西了。这个周末都加了两天班。公司的新项目都是采用.netcore来开发,在开发过程中,也踩到了一些坑,在此先总结两个坑,这两个坑都是关于Linux(CentOS)和windows下的兼容性问题。我们最开始的开发环境接口调用一直是部署在windows环境运行一切正常,但是部署到Linux(CentOS)环境下,就出现了这两个问题,其实问题也简单:获取系统时间,实际时间少了8个小时;文件路径​被识别为了文件名。下面就简单分享一下解决方式,其实只要你一看,发现很简单的,之所以分享出来,当你才开始用户.netcore时,可以有一个提示作用,嘿嘿!

    END
    为了更高的交流,欢迎大家关注我的公众号,扫描下面二维码即可关注,谢谢:

  • 相关阅读:
    k近邻 KNN
    聚类之k-means
    支持向量机SVM、优化问题、核函数
    [THUSC 2016] 补退选 (Trie树)
    [CQOI2016] 手机号码 (数位dp)
    [CQOI2012] 交换棋子 (费用流)
    [SCOI2016] 背单词 (Trie树)
    [JSOI2009] 球队收益 (费用流)
    [BZOJ1878][SDOI2009] HH的项链 (树状数组)
    [BZOJ2151]种树
  • 原文地址:https://www.cnblogs.com/xiaoXuZhi/p/netcoredatetime.html
Copyright © 2011-2022 走看看