1/**
2 * $RCSfile$
3 * $Revision$
4 * $Date$
5 *
6 * Copyright 2003-2007 Jive Software.
7 *
8 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *     http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package org.jivesoftware.smackx.packet;
22
23import org.jivesoftware.smack.packet.IQ;
24
25import java.text.DateFormat;
26import java.text.SimpleDateFormat;
27import java.util.Calendar;
28import java.util.Date;
29import java.util.TimeZone;
30
31/**
32 * A Time IQ packet, which is used by XMPP clients to exchange their respective local
33 * times. Clients that wish to fully support the entitity time protocol should register
34 * a PacketListener for incoming time requests that then respond with the local time.
35 * This class can be used to request the time from other clients, such as in the
36 * following code snippet:
37 *
38 * <pre>
39 * // Request the time from a remote user.
40 * Time timeRequest = new Time();
41 * timeRequest.setType(IQ.Type.GET);
42 * timeRequest.setTo(someUser@example.com/resource);
43 *
44 * // Create a packet collector to listen for a response.
45 * PacketCollector collector = con.createPacketCollector(
46 *                new PacketIDFilter(timeRequest.getPacketID()));
47 *
48 * con.sendPacket(timeRequest);
49 *
50 * // Wait up to 5 seconds for a result.
51 * IQ result = (IQ)collector.nextResult(5000);
52 * if (result != null && result.getType() == IQ.Type.RESULT) {
53 *     Time timeResult = (Time)result;
54 *     // Do something with result...
55 * }</pre><p>
56 *
57 * Warning: this is an non-standard protocol documented by
58 * <a href="http://www.xmpp.org/extensions/xep-0090.html">XEP-0090</a>. Because this is a
59 * non-standard protocol, it is subject to change.
60 *
61 * @author Matt Tucker
62 */
63public class Time extends IQ {
64
65    private static SimpleDateFormat utcFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
66    private static DateFormat displayFormat = DateFormat.getDateTimeInstance();
67
68    private String utc = null;
69    private String tz = null;
70    private String display = null;
71
72    /**
73     * Creates a new Time instance with empty values for all fields.
74     */
75    public Time() {
76
77    }
78
79    /**
80     * Creates a new Time instance using the specified calendar instance as
81     * the time value to send.
82     *
83     * @param cal the time value.
84     */
85    public Time(Calendar cal) {
86        TimeZone timeZone = cal.getTimeZone();
87        tz = cal.getTimeZone().getID();
88        display = displayFormat.format(cal.getTime());
89        // Convert local time to the UTC time.
90        utc = utcFormat.format(new Date(
91                cal.getTimeInMillis() - timeZone.getOffset(cal.getTimeInMillis())));
92    }
93
94    /**
95     * Returns the local time or <tt>null</tt> if the time hasn't been set.
96     *
97     * @return the lcocal time.
98     */
99    public Date getTime() {
100        if (utc == null) {
101            return null;
102        }
103        Date date = null;
104        try {
105            Calendar cal = Calendar.getInstance();
106            // Convert the UTC time to local time.
107            cal.setTime(new Date(utcFormat.parse(utc).getTime() +
108                    cal.getTimeZone().getOffset(cal.getTimeInMillis())));
109            date = cal.getTime();
110        }
111        catch (Exception e) {
112            e.printStackTrace();
113        }
114        return date;
115    }
116
117    /**
118     * Sets the time using the local time.
119     *
120     * @param time the current local time.
121     */
122    public void setTime(Date time) {
123        // Convert local time to UTC time.
124        utc = utcFormat.format(new Date(
125                time.getTime() - TimeZone.getDefault().getOffset(time.getTime())));
126    }
127
128    /**
129     * Returns the time as a UTC formatted String using the format CCYYMMDDThh:mm:ss.
130     *
131     * @return the time as a UTC formatted String.
132     */
133    public String getUtc() {
134        return utc;
135    }
136
137    /**
138     * Sets the time using UTC formatted String in the format CCYYMMDDThh:mm:ss.
139     *
140     * @param utc the time using a formatted String.
141     */
142    public void setUtc(String utc) {
143        this.utc = utc;
144
145    }
146
147    /**
148     * Returns the time zone.
149     *
150     * @return the time zone.
151     */
152    public String getTz() {
153        return tz;
154    }
155
156    /**
157     * Sets the time zone.
158     *
159     * @param tz the time zone.
160     */
161    public void setTz(String tz) {
162        this.tz = tz;
163    }
164
165    /**
166     * Returns the local (non-utc) time in human-friendly format.
167     *
168     * @return the local time in human-friendly format.
169     */
170    public String getDisplay() {
171        return display;
172    }
173
174    /**
175     * Sets the local time in human-friendly format.
176     *
177     * @param display the local time in human-friendly format.
178     */
179    public void setDisplay(String display) {
180        this.display = display;
181    }
182
183    public String getChildElementXML() {
184        StringBuilder buf = new StringBuilder();
185        buf.append("<query xmlns=\"jabber:iq:time\">");
186        if (utc != null) {
187            buf.append("<utc>").append(utc).append("</utc>");
188        }
189        if (tz != null) {
190            buf.append("<tz>").append(tz).append("</tz>");
191        }
192        if (display != null) {
193            buf.append("<display>").append(display).append("</display>");
194        }
195        buf.append("</query>");
196        return buf.toString();
197    }
198}