.NET WebFrom跨時區項目時間問題處理方法

来源:https://www.cnblogs.com/kaizishu/archive/2019/09/25/11586044.html
-Advertisement-
Play Games

前段時間因為公司的一個 WebFrom 項目設計到跨時區的問題,處理了一段時間,終於解決了,寫個博客記錄一下,方便以後回顧以及給他人提供一個參考的方法。 本次的項目因為跨越了多個時區,在一些時間上會受到時區的影響,比如在美國分部使用系統插入了一條數據,在美國分部顯示的時間是“2019-09-25 0 ...


  前段時間因為公司的一個 WebFrom 項目設計到跨時區的問題,處理了一段時間,終於解決了,寫個博客記錄一下,方便以後回顧以及給他人提供一個參考的方法。

  本次的項目因為跨越了多個時區,在一些時間上會受到時區的影響,比如在美國分部使用系統插入了一條數據,在美國分部顯示的時間是“2019-09-25 00:00:00“,那麼在北京分部看到的時間就應該自動轉換成”2019-09-25 12:00:00“(美國比北京少十二個小時),因此系統要能實現自動獲取客戶端的時區並轉換成 UTC 時間,保存到資料庫,在取出來的時候再根據客戶端時區轉換為當地時間。

  一開始是受部門運維的引導,知道了 oracle 自帶一種數據類型叫做 timestamp with local time zone ,即按照資料庫緩存的時區(Database Session Timezone),當用戶存取時間時按照用戶 Session 的時區對時間欄位轉換為當地時間。這個在我 CSDN 的博客中有提到這樣的東西,鏈接為:https://blog.csdn.net/Wujiakai123/article/details/95391436 。然而當我開始嘗試在項目中改進的時候才發現,發佈到 IIS 的項目,不管有多少個客戶連接進來,始終是以我的伺服器為客戶端去連接 oracle 的,這就導致了 oracle 中 Session 的時區一直是我的伺服器的時區。因此推翻了使用 oracle 自帶數據類型對時間欄位進行自動轉換的方法。

  此路不通,所以就只能嘗試在項目裡面做改進了。經過與部門其他同事討論之後,決定在登錄時通過 JS 方法獲取到客戶端電腦的時區,保存到用戶的登錄信息中,這樣,在用戶進行操作時,涉及到時間的都按照該時區進行轉換。因為本人剛畢業不久,代碼技術水平不高,因此只想出了這樣的笨方法,下麵將具體實現方法列出來,如果有大佬有更好的解決辦法歡迎評論,我可以多學習學習。

  Login.aspx:

                <div class="newBox">
                    <asp:HiddenField ID="hidTimezone" runat="server" ClientIDMode="Static" />  //
                    <asp:Button ID="btnLogin" CssClass="LoginBtn" runat="server" OnClientClick="Login()"
                        Text="Sign In" OnClick="btnLogin_Click" />
                </div>

  hidTimezone 控制項用於保存當前用戶瀏覽器時區的值,btnLogin 按鈕點擊調用 Login() 方法

  Login()方法:

    <script type="text/javascript">
        
        function Login() {

            //得到本地時間
            var d = new Date();
            //得到1970年一月一日到現在的秒數
            var local = d.getTime();
            //本地時間與GMT時間的時間偏移差
            var offset = d.getTimezoneOffset() * 60000;
            //獲取本地時區,判斷如果是負的則相加得到格林尼治時間,正的則相減
            var timezone = new Date().getTimezoneOffset() / 60 * (-1);
            document.getElementById("hidTimezone").value = timezone.toString();

            return true;
        }
    </script>

  通過 JS 方法將獲取到的時區的值賦給 hidTimezone 中,登錄的時候將該控制項的值跟著用戶的登錄信息一起放在 Session 中,大概就是這樣:

UserModel model = new UserModel();
model.Timezone = Convert.ToDouble(hidTimezone.value); 
Session[
"UserModelInfo"] = model;

  這樣子就能將用戶的瀏覽器時區寫入到 Session 中,方便後續做時間轉換的時候可使用。

  因為系統中所有頁面都是繼承了模板頁 BasePage ,因此只要在模板頁獲取時區信息就可以了。

private UserLoginInfo _UserLoginInfo;
protected override void OnLoad(EventArgs e)
{
    _UserLoginInfo = (UserLoginInfo)Session["UserLoginInfo"];    
    base.OnLoad(e);
}

public class UserLoginInfo
{
    /// <summary>
    /// 用戶所在時區
    /// </summary>
    public double Timezone { get; set; }
}

  這樣一來,只要頁面繼承了 BasePage,就可以用 base.UserLoginInfo.Timezone 獲取到時區信息。

  在Helper 類中新增時區轉換方法:

       /// <summary>
        /// 根據時區獲取本地時間
        /// </summary>
        /// <param name="timezone">時區</param>
        /// <returns></returns>
        public static DateTime GetLocalTime(double timezone)
        {
            try
            {
                double min = timezone * 60;
                var localtime = DateTime.UtcNow.AddMinutes(min);
                return localtime;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex.Message);
                throw new Exception(ex.Message);
            }

        }

        /// <summary>
        /// 根據時區將UTC時間轉換成本地時間
        /// </summary>
        /// <param name="UTCTime">資料庫中保存的UTC時間</param>
        /// <param name="timezone">用戶本地電腦時區</param>
        /// <returns></returns>
        public static DateTime UTCToLocal(DateTime UTCTime, double timezone)
        {
            try
            {
                double min = timezone * 60;
                var localtime = UTCTime.AddMinutes(min);
                return localtime;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex.Message);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 根據時區將本地時間轉換成UTC時間
        /// </summary>
        /// <param name="UTCTime">資料庫中保存的UTC時間</param>
        /// <param name="timezone">用戶本地電腦時區</param>
        /// <returns></returns>
        public static DateTime LocalToUTC(DateTime localtime, double timezone)
        {
            try
            {
                double min = timezone * 60 * (-1);
                var UTCTime = localtime.AddMinutes(min);
                return UTCTime;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex.Message);
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 將時區信息轉換為分鐘偏移量
        /// 例:GMT+09:00 轉換結果為:540
        /// </summary>
        /// <param name="timezone">時區信息</param>
        /// <returns></returns>
        public static double GetTimezoneMinOffset(string timezone)
        {
            try
            {
                string strSub = timezone.Substring(timezone.Length - 6, 6);

                string[] timestr = strSub.Split(':');
                double min;
                if (Convert.ToDouble(timestr[0]) < 0)
                {
                    min = Convert.ToDouble(timestr[0]) * 60 - Convert.ToDouble(timestr[1]);
                }
                else
                {
                    min = Convert.ToDouble(timestr[0]) * 60 + Convert.ToDouble(timestr[1]);
                }
                return min;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex.Message);
                throw new Exception(ex.Message);
            }

        }

  這樣子就成功了一半了,接下來要做的,就是將原本系統中,執行 Insert 語句插入資料庫之前獲取數據中時間的 DateTime.Now 統一改成 DateTime.UtcNow,就能保證數據保存到資料庫中是以當前 UTC 時間進行保存的,若涉及到時間,可用以上方法進行轉換之後再保存到資料庫中。同理,當用戶查看數據時,涉及到時間的也根據以上方法,將資料庫中的 UTC 時間轉換成當地時間顯示。這樣一來就可以實現不同時區的人無論存數據或者查看數據都按照當地的時區。

  那以上就是我對於 .NET WebFrom 項目跨時區的一個比較愚鈍的解決辦法,我相信肯定會有更方便更容易的方法,只是在當時項目趕著交付的情況下,我直接選取了這種比較笨的方法,優點就是用戶是無感知的,在登錄的時候就已經自動獲取到了用戶的時區信息,獲取數據時也自動轉換出來,對於用戶來說不用特地去維護自己的時區信息。當然缺點就是這樣一來,這套項目往後所有有關時間的信息都要按照這樣的轉換,若是有遺漏了,就會出現時間上不統一的問題,對應項目的再次開發以及以後交付給他人都是一個負擔。

  如果各位大佬有其他更好的方法歡迎評論區留言,讓我這個菜鳥能多學習學習。這次也是第一次在博客園寫博客,怎麼說呢,自己本身基礎並不扎實,還在學習中,若有不對之處請盡請指出!多謝各位!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 安裝ptyhon3.7 sudo apt-get update sudo apt-get install python3.7 安裝成後的目錄在/usr/bin/python3.7,同時將其設置成預設 sudo update-alternatives --install /usr/bin/python ...
  • DRF框架中鏈表數據通過ModelSerializer深度查詢方法彙總 一.準備測試和理解準備 創建類 生成表單數據 Test1 id| test_2_id_id | 1|1 2|2 Test2 id|name | 1|名字1 2|名字2 二.深度查詢通過Test1獲得Test2的name而不是id ...
  • 需求:隨機生成驗證碼, 思路: 1.生成一個隨機數,65-90 2.數字轉化為字母:chr(數字) 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import random 5 temp = "" 6 for i in range(6): ...
  • [TOC] 一:序列     在數學上,序列是被排成一排的對象,而在python中,序列是最基本的數據結構。它的主要特征為擁有索引,每個索引的元素是可迭代對象。都可以進行索引,切片,加,乘,檢查成員等操作。在python中,有六種內建的索引,但是常用的是列表,元組,字元 ...
  • 這是大佬老A寫的一篇介紹Asp.Net core框架的文章https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 2001年,微軟推出了Asp.Net ,2009年,推出了Asp.Net MVC .Net Framewo ...
  • 一、多態 多態是從繼承中引出來的概念,即不同的派生類對基類的相同方法表現出不同的行為。如下麵例子中動物的游泳方法: 當用戶使用派生類雞的游泳方法時,由於基類的游泳方法滿足雞的需求,則直接調用基類的游泳方法返回不會;當用戶使用派生類狗和蛙的游泳方法時,由於基類的游泳方法的實現不滿足狗和蛙的需求,所以狗 ...
  • 你是不是羡慕Java SpringBoot里功能強大的@註解功能,Spring Boot倡導是一種開箱即用、方便快捷、約定優於配置的開發流程,雖然現在.NET Core也往相同的方向走,但在使用上總有點彆扭,目前市面上貌似還沒有輕量級的真正意義上的開箱即用的基於.NET Core的框架。 想想多年前 ...
  • 場景 Winforn中設置ZedGraph曲線圖的屬性、坐標軸屬性、刻度屬性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100112573 在主窗體中有一個ZedGraphControl控制項,如果要在本窗體獲取此控制項對象則通 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...