聊聊.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。具体实现代码如下:

       

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <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

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/* ==============================================================================
 * 功能描述:所有时间的相关操作集合 
 * 创 建 者:程序修炼之旅 交流微信号: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
为了更高的交流,欢迎大家关注我的公众号,扫描下面二维码即可关注,谢谢:

 

 

 

 

posted @   程序员修炼之旅  阅读(3339)  评论(26编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
END
欢迎各位小伙伴关注我的公众号(程序员修炼之旅),里面会分享一些技术类干货,同时也是一个技术沟通交流平台,谢谢大家的支持。
点击右上角即可分享
微信分享提示