對中國標準時間(CST)和中國夏令時(CDT)的不同處理

問題重現:

通過接口從後端獲取時間戳,在前端用JS格式化顯示。發現Chrome在Mac和Windows下,對特定的時間段(1986年至1991年),的處理方式並不相同。

 

問題產生原因:

查詢資料後發現,原來中國也曾經使用過夏令時。

1986年至1991年,中華人民共和國在全國範圍實行了六年夏令時,每年從4月中旬的第一個星期日2時整(北京時間)到9月中旬第一個星期日的凌晨2時整(北京夏令時)。除1986
年因是實行夏令時的第一年,從5月4日開始到9月14日結束外,其它年份均按規定的時段施行。1992年4月5日後不再實行。

要避免此情況可在後端對時間進行處理,返回格式化後的日期字符串。

1

TimeZone.setDefault(TimeZone.getTimeZone("GMT+8:00"));

或在前端通過getTimezoneOffset檢測夏令時,嘗試網上找到的夏令時檢測算法。(不推薦)

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

<!DOCTYPE html>

<html>

    <head>

    <title>DST Calculator</title>

    <script type="text/javascript">

 

    function DisplayDstSwitchDates()

    {

        var year = new Date().getYear();

        if (year < 1000)

            year += 1900;

 

        var firstSwitch = 0;

        var secondSwitch = 0;

        var lastOffset = 99;

 

        // Loop through every month of the current year

        for (i = 0; i < 12; i++)

        {

            // Fetch the timezone value for the month

            var newDate = new Date(Date.UTC(year, i, 0, 0, 0, 0, 0));

            var tz = -1 * newDate.getTimezoneOffset() / 60;

 

            // Capture when a timzezone change occurs

            if (tz > lastOffset)

                firstSwitch = i-1;

            else if (tz < lastOffset)

                secondSwitch = i-1;

 

            lastOffset = tz;

        }

 

        // Go figure out date/time occurences a minute before

        // a DST adjustment occurs

        var secondDstDate = FindDstSwitchDate(year, secondSwitch);

        var firstDstDate = FindDstSwitchDate(year, firstSwitch);

 

        if (firstDstDate == null && secondDstDate == null)

            return 'Daylight Savings is not observed in your timezone.';

        else

            return 'Last minute before DST change occurs in ' +

               year + ': ' + firstDstDate + ' and ' + secondDstDate;

    }

 

    function FindDstSwitchDate(year, month)

    {

        // Set the starting date

        var baseDate = new Date(Date.UTC(year, month, 0, 0, 0, 0, 0));

        var changeDay = 0;

        var changeMinute = -1;

        var baseOffset = -1 * baseDate.getTimezoneOffset() / 60;

        var dstDate;

 

        // Loop to find the exact day a timezone adjust occurs

        for (day = 0; day < 50; day++)

        {

            var tmpDate = new Date(Date.UTC(year, month, day, 0, 0, 0, 0));

            var tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;

 

            // Check if the timezone changed from one day to the next

            if (tmpOffset != baseOffset)

            {

                var minutes = 0;

                changeDay = day;

 

                // Back-up one day and grap the offset

                tmpDate = new Date(Date.UTC(year, month, day-1, 0, 0, 0, 0));

                tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;

 

                // Count the minutes until a timezone chnage occurs

                while (changeMinute == -1)

                {

                    tmpDate = new Date(Date.UTC(year, month, day-1, 0, minutes, 0, 0));

                    tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;

 

                    // Determine the exact minute a timezone change

                    // occurs

                    if (tmpOffset != baseOffset)

                    {

                        // Back-up a minute to get the date/time just

                        // before a timezone change occurs

                        tmpOffset = new Date(Date.UTC(year, month,

                                             day-1, 0, minutes-1, 0, 0));

                        changeMinute = minutes;

                        break;

                    }

                    else

                        minutes++;

                }

 

                // Add a month (for display) since JavaScript counts

                // months from 0 to 11

                dstDate = tmpOffset.getMonth() + 1;

 

                // Pad the month as needed

                if (dstDate < 10) dstDate = "0" + dstDate;

 

                // Add the day and year

                dstDate += '/' + tmpOffset.getDate() + '/' + year + ' ';

                // Capture the time stamp

                tmpDate = new Date(Date.UTC(year, month,

                                   day-1, 0, minutes-1, 0, 0));

                dstDate += tmpDate.toTimeString().split(' ')[0];

                return dstDate;

            }

        }

    }

 

    </script>

    </head>

    <body>

        <script type="text/javascript">

            document.write("Current date/time: " + new Date() + "<br />");

            document.write(DisplayDstSwitchDates());

        </script>

    </body>

</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章