回 帖 发 新 帖 刷新版面

主题:如何获取服务器时间的时区

我想获取系统的时区怎么获取啊,比如北京时区得到+8。
系统是运行在 linux上的。

通过java得到时区更好,不行的话读取linux系统文件也可以。

回复列表 (共4个回复)

沙发

Calendar now_Time=Calendar.getInstance(TimeZone.getTimeZone("Asia/ShangHai"));  //这个是得到上每的时间.
  你可以给其它地区名,就行了.
http://www.ibm.com/developerworks/cn/java/l-datetime/part2/index.html
  这里有个说明,你可以参考一下.

板凳

Java 中定义了TimeZone 对象,它和Calendar一样是个抽象类。Java的SimpleTimeZone对象则提供了真正的实现。
首先我们来看一个简单的需求,将当前时间转换到另一时区的时间:
例如我们将 2001 年 8 月 1 日 0 时 0 分,当前时区下的时间转换成在 GMT 下同一时刻的时间
import java.io.*;
import java.util.*;
public class TimeZoneConversion
{
    public static void main(String[] args) throws Exception{
        // 这也是获得当前时间的一种方式
        Calendar cal1 = Calendar.getInstance();
        cal1.set(2001, 7, 1, 0, 0, 0);
        // 显示当前的时间
        System.out.println(cal1.getTime());
        // 显示该 Calendar 的时区
        System.out.println(cal1.getTimeZone().getID());
        cal1.setTimeZone(TimeZone.getTimeZone("GMT"));      
        // 似乎这样就可以获得在 GMT 下的时间
        System.out.println(cal1.getTime());
        System.out.println(cal1.getTimeZone().getID());
    }
}

但是结果却是没有改变,看来 Calendar 是基于保存下来的 millisecond 值,而不是根据 TimeZone 的更改而变化的,下面的程序说明了这一点:
import java.io.*;
import java.util.*;
public class TimeZoneConversion
{
    public static void main(String[] args) throws Exception{
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        Calendar cal1 = Calendar.getInstance();
        cal1.set(2001, 7, 1, 0, 0, 0);
        System.out.println(cal1.getTime());
// 在当前的时区下,我们指定了时间是 8 月,显示 7
        System.out.println(cal1.get(Calendar.MONTH));
// 在当前的时区下,我们指定了时间是 1 日,显示 1
        System.out.println(cal1.get(Calendar.DATE));
// 在当前的时区下,我们指定了时间是 0 时,显示 0
        System.out.println(cal1.get(Calendar.HOUR_OF_DAY));
        System.out.println(cal1.getTimeZone().getID());
        cal1.setTimeZone(TimeZone.getTimeZone("GMT"));
        System.out.println(cal1.getTime());
        System.out.println(cal1.getTimeZone().getID());
        // 由于实际保存的时间没有修改,在 GMT 下,由于时差,显示 6 (7月)
        System.out.println(cal1.get(Calendar.MONTH));
        // 在 GMT 下,由于时差,显示 31
        System.out.println(cal1.get(Calendar.DATE));
        // 由于更改了时区,在 GMT 下时间就会变成 16,8个小时时差
        System.out.println(cal1.get(Calendar.HOUR_OF_DAY));
    }
}

3 楼

那如果我们是要得到 GMT 下的 2001/8/1 00:00,如何得到呢?只需要加上一行代码
   cal1.set(Calendar.MILLISECOND, 0); // 或者任何值
import java.io.*;
import java.util.*;
public class TimeZoneConversion
{
    public static void main(String[] args) throws Exception{
        Calendar cal1 = Calendar.getInstance();
        cal1.set(2001, 7, 1, 0, 0, 0);
        System.out.println(cal1.getTime());
        System.out.println(cal1.get(Calendar.MONTH));
        System.out.println(cal1.get(Calendar.DATE));
        System.out.println(cal1.get(Calendar.HOUR_OF_DAY));
        System.out.println(cal1.getTimeZone().getID());
        cal1.setTimeZone(TimeZone.getTimeZone("GMT"));
        // 如果取消下面代码的注释,结果就和前面的一样
        //int save = cal1.get(Calendar.MILLISECOND);
        cal1.set(Calendar.MILLISECOND, 0);
        System.out.println(cal1.getTime());
        System.out.println(cal1.getTimeZone().getID());
        System.out.println(cal1.get(Calendar.MONTH));
        System.out.println(cal1.get(Calendar.DATE));
        System.out.println(cal1.get(Calendar.HOUR_OF_DAY));
    }
}

这里要注意的是,如何在修改完Calendar的TimeZone与第一次调用set()方法间,调用了get()/add()等方法,那么Calendar将锁定其所保存的millisecond值。大家可以自己执行上面的程序来了解这个区别。由于很少有应用程序精确到MILLISECOND级别,所以我们将其置为0的作法是可以接受的。
然后我们来看另一个非常重要的问题,如何将时间保存到数据库中:
不同的数据库对时间的表示是不同的,这个问题对于开发支持多个数据库的开发商而言,需要额外地注意。我们将在 Timestamp中来介绍这个问题及解决方案。但是它们的一个共性是,它们都忽略TimeZone。当我们将 2001/8/1 00:00 CST保存到数据库时,它的结果就是:"2001-08-01 00:00:00.0"。那么就有一个隐含的问题存在了,如果我们有两个客户一个在中国,将这个时间写入到数据库中;另一个客户在GMT时区下,将这个数据取出,它会得到什么结果呢?
       Calendar cal1 = Calendar.getInstance();
        cal1.set(2001, 7, 1, 0, 0, 0);
        Timestamp ts = new Timestamp(cal1.getTime().getTime());
        System.out.println(ts.getTime());
        // 获得数据库连接
        Connetion conn = …;
        Statement stmt = conn.createStatement();
// 执行SQL 语句"update EMPLOYEE set STARTTIME=' 
2001-08-01 00:00:00.0' where ID=1" stmt.executeUpdate
("update EMPLOYEE set STARTTIME='"+ts+"' where ID=1");
// 我们动态更改JVM的TimeZone来模拟另一客户在不同TimeZone下的访问
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
ResultSet rs = stmt.executeQuery
("select STARTTIME from EMPLOYEE where ID=1");
if (rs.next())
  Timestamp ts = rs.getTimestamp(1);
// 结果竟然与前面的不一致
System.out.println(ts.getTime());

也就是说,当JDBC将时间保存到数据库中时,它根据当前JVM的时区将时间传递给数据库保存。当该时间在另一个时区下取出的时候,以该时区还原。而这个还原不是根据其所表示的MilliSecond来进行的。这个问题对要支持多时区客户端同时访问数据库的同一时间而言是致命的问题。根本的解决方法是,JDBC程序对数据库中的时间有一个公认的TimeZone。在JVM中我们用GMT时区下的MilliSecond,来同一了对时间的表述。我们可以将同样的方法拓展到数据库中的保存。我们需要在JDBC上加一层我们自己的API,在这一层中我们将Date/Timestamp先转换成GMT下的表示进行保存,在取回时基于GMT再转换回来。由于我们对数据库的操作还是要通过低层的JDBC进行,所以我们还要欺骗它(因为它总是使用当前JVM的时区进行转换的)。
如:2001-08-01 00:00 CST,对应GMT下的时间应为 2001-07-31 16:00 GMT JDBC 保存时该时间时,我们应该要在数据库中得到"2001-07-31 16:00",这样我们在取回时就得到正确的时间表述了。
public static Calendar toGMT(Calendar cal) {
    // 也可以用 Calendar cal1 = Calendar.getInstance();
        Calendar cal1 = (Calendar)cal.clone();      
        // 先保存原来的时区
        TimeZone tzSave = cal.getTimeZone();
        // 将时区转换到GMT下
        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
        // 将GMT下的年月日等信息再填回到当前时区下的Calendar
        cal1.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)
        , cal.get(Calendar.DATE), cal.get(Calendar.HOUR_OF_DAY)
        , cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        cal1.set(Calendar.MILLISECOND, cal.get(Calendar.MILLISECOND));
        // 恢复原来的时区
        cal.setTimeZone(tzSave);
        // 锁定MilliSecond
        cal.getTime();
        return cal1;
    }
   

4 楼

可能我没有把意思说明白,由于系统不知道在哪个国家运行,所以就无法指定时区("Asia/ShangHai")。

这个问题解决了,是通过获取linux返回值得到结果 的,执行dump -v TS 获取系统的夏令时结果,得到当地时间以及时区的。具体实现就不细说了,感兴趣的自己可以研究一下linux

我来回复

您尚未登录,请登录后再回复。点此登录或注册