c# – 当中国的时区走的时候,好的Java不会工作吗?

前端之家收集整理的这篇文章主要介绍了c# – 当中国的时区走的时候,好的Java不会工作吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
由于某些游戏开发可能会使用过去或未来的日期时间,以及日期时间模拟的任何时区,即使我们从未实际接触过它们.对于这个假设,并不是说我在假日期时计算,而是在任何时区的任何日期时间计算的正确性,就像它实际上一样.

我之前曾问过一个关于中国在Java中的时区问题的问题,这被认为是一个重复的问题,我就删除了它.但是,从这个comment thread开始,我知道Java中存在某种时间倒带(转换?)问题,而不仅仅是时区变化.

现在,我以不同的方式重新发布此问题,以便通过以下方式提出此问题:

> Java代码

import org.joda.time.*;
import java.util.*;

class PandaTest {
    static long Subtract(
        Date minuend,Date subtrahend,DateTimeZone zone) {
        long millis;

        if(null==zone)
            millis=minuend.getTime()-subtrahend.getTime();
        else {
            long rhs=
                (new LocalDateTime(subtrahend)).toDateTime(zone)
                .getMillis();

            long lhs=
                (new LocalDateTime(minuend)).toDateTime(zone)
                .getMillis();

            millis=lhs-rhs;
        }

        return millis/1000;
    }

    static Date MakeTime(
        int year,int month,int day,int hour,int minute,int second
        ) {
        Calendar calendar=
            Calendar.getInstance(TimeZone.getTimeZone("PRC"));

        calendar.set(year,month-1,day,hour,minute,second);
        return calendar.getTime();
    }

    static void puts(String arg0) {
        System.out.println(arg0);
    }

    static void ShowDuration(DateTimeZone zone,Date ... args) {
        int argc=args.length;

        puts("--- ");
        puts("Time Zone: "+(null!=zone?zone.toString():"unspecified"));

        for(int i=0; argc-->0; ++i) {
            puts("Time "+i+": "+args[i]);

            if(i>0) {
                long duration=Subtract(args[i],args[i-1],zone);
                puts("Duration = "+duration);
            }
        }
    }

    public static void main(String[] args) {
        Date retainsOfTheDay=MakeTime(1900,1,8,5,51+0);
        Date somewhereInTime=MakeTime(1900,51+1);
        DateTimeZone zone=DateTimeZone.forID("PRC");
        ShowDuration(null,retainsOfTheDay,somewhereInTime);
        ShowDuration(zone,somewhereInTime);
    }
}

如果我从Java的日期构造了JodaTime的LocalDateTime,则会出现问题. JDK的版本是7u17,JodaTime是2.2.在NodaTime的C#中不会发生这种情况,我在这篇文章的后面添加了替代版本的代码以进行对比.

>问题

>转换是如何发生的,它与Unix Epoch一样精确吗?

我可能以错误的方式使用术语转换.我的意思是在Java中以1900/1/1 8:5:51减去1900/1/1 8:5:52的奇怪结果.那时没有时区变化.

这样的事情只发生在特定时区或所有时区(可能在某个不同时刻)吗?
>如果可以在任何时区的任意日期时间计算,期望结果总是正确的,是否应该使用日期和日历?

如果是,如何在没有问题的情况下使用它们?

一旦我们计算出1970年之前或2038年之后的日期时间,我们是否应该再使用Java中的日期和日历?

替代准则

代码包含C#和Java中的内容,我们可以方便地对比C#和Java中的结果:

// Like Java,like Sharp ... the code contains content either in Java or C# 
// An odd number of `slash-star-slash` at the beginning to compile in Java
// An even number of `slash-star-slash` at the beginning to compile in C#
// p.s.: zero would be treated as an even number

using Date=System.DateTime;
using NodaTime.TimeZones;
using NodaTime;
using System.Collections.Generic;
using System.Linq;
using System; /*/
import org.joda.time.*;
import java.util.*;

// ClockCant in Java 
class ClockCant {
    public static Date MakeTime(
        int year,second);
        return calendar.getTime();
    }

    public static DateTimeZone GetZoneFromId(String id) {
        return DateTimeZone.forID(id);
    }

    public static String GetYourZoneId() {
        return DateTimeZone.getDefault().getID();
    }

    public static long Subtract(
        Date minuend,DateTimeZone zone) {
        long millis;

        if(null==zone)
            millis=minuend.getTime()-subtrahend.getTime();
        else {
            long rhs=
                (new LocalDateTime(subtrahend)).toDateTime(zone)
                .getMillis();

            long lhs=
                (new LocalDateTime(minuend)).toDateTime(zone)
                .getMillis();

            millis=lhs-rhs;
        }

        return millis/1000;
    }
}

// a minimum implementation of C#-like List<T> for Java
class List<T> {
    public T[] ToArray() {
        return _items;
    }

    public int Count() {
        return _items.length;
    }

    public List(T ... args) {
        _items=args;
    }

    T[] _items;
}

/*/// ClockCant in C#
class ClockCant {
    public static Date MakeTime(
        int year,int second) {
        return new Date(year,month,second);
    }

    public static DateTimeZone GetZoneFromId(String id) {
        return DateTimeZoneProviders.Tzdb[id];
    }

    public static String GetYourZoneId() {
        return DateTimeZoneProviders.Tzdb.GetSystemDefault().Id;
    }

    public static long Subtract(
        Date minuend,DateTimeZone zone) {
        long ticks;

        if(null==zone)
            ticks=minuend.Subtract(subtrahend).Ticks;
        else {
            var rhs=
                LocalDateTime.FromDateTime(subtrahend)
                .InZoneLeniently(zone);

            var lhs=
                LocalDateTime.FromDateTime(minuend)
                .InZoneLeniently(zone);

            ticks=(lhs.ToInstant()-rhs.ToInstant()).Ticks;
        }

        return ticks/TimeSpan.TicksPerSecond;
    }
}

// extension for Java-like methods in C#
static partial class JavaExtensions {
    public static String toString(this Object x) {
        return x.ToString();
    }
}

class PandaTest { /*/ class PandaTest {
    // in Java
    public static void main(String[] args) {
        Language="Java";
        Main(args);
    }

    static void puts(String arg0) {
        System.out.println(arg0);
    }

    static void ShowDuration(DateTimeZone zone,Date ... args) {
        ShowDuration(zone,new List<Date>(args));
    }

    /*/// in C#
    static void puts(String arg0) {
        Console.WriteLine(arg0);
    }

    static void ShowDuration(DateTimeZone zone,params Date[] args) {
        ShowDuration(zone,args.ToList());
    }

    /**/// the following code are for both C# and Java
    static void ShowDuration(DateTimeZone zone,List<Date> args) {
        int argc=args.Count();
        Date[] argv=args.ToArray();

        puts("--- ");
        puts("Time Zone: "+(null!=zone?zone.toString():"unspecified"));

        for(int i=0; argc-->0; ++i) {
            puts("Time "+i+": "+argv[i]);

            if(i>0) {
                long duration=ClockCant.Subtract(argv[i],argv[i-1],zone);
                puts("Duration = "+duration);
            }
        }
    }

    static void Main(String[] args) {
        Date retainsOfTheDay=ClockCant.MakeTime(1900,51+0);
        Date somewhereInTime=ClockCant.MakeTime(1900,51+1);
        DateTimeZone zone=ClockCant.GetZoneFromId("PRC");
        puts("Current Time Zone: "+ClockCant.GetYourZoneId());
        puts("Language: "+Language);
        ShowDuration(null,somewhereInTime);
    }

    static String Language="C#";
}

要在Java中编译,请在代码的开头添加/ * /,如下所示:

/*/// Like Java,like Sharp ...

解决方法

我相信你的Joda Time测试被打破了,因为你已经使它变得不必要地复杂,基本上.这是一个简短但完整的程序,展示了不同之处:
import java.util.*;
import org.joda.time.*;

public class ChinaTest {
    public static void main(String[] args) {
        DateTime startOf1900 = new DateTime(1900,DateTimeZone.UTC);
        DateTime endOf1899 = startOf1900.minusMillis(1);

        DateTimeZone jodaZone = DateTimeZone.forID("Asia/Shanghai");
        System.out.println("Joda at start of 1900: " +
                           jodaZone.getOffset(startOf1900));
        System.out.println("Joda at end of 1899: " +
                           jodaZone.getOffset(endOf1899));
        TimeZone javaZone = TimeZone.getTimeZone("Asia/Shanghai");
        System.out.println("Java at start of 1900: " + 
                           javaZone.getOffset(startOf1900.getMillis()));
        System.out.println("Java at end of 1899: " + 
                           javaZone.getOffset(startOf1900.getMillis() - 1));
    }
}

输出

Joda at start of 1900: 29152000
Joda at end of 1899: 29152000
Java at start of 1900: 29152000
Java at end of 1899: 28800000

所以基本上,Java的时区认为在1900年初有一个过渡,而Joda Time则没有.

正如我之前所写的那样,Java的时区实现基本上假设在1900年UTC开始之前不存在夏令时 – 所以在夏令时在1900年开始生效的任何时区,这代表了转换.

Joda Time和Noda Time都没有做出这样的假设,这就是你看到差异的原因.

这与Unix时代无关,也与2038无关.这意味着你应该期望java.util.TimeZone将1900 UTC开始之前的任何日期/时间视为该时区的“标准时间”.

原文链接:https://www.f2er.com/csharp/243520.html

猜你在找的C#相关文章