001/* 002 * 003 * Copyright 2003-2007 Jive Software, 2014-2025 Florian Schmaus 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.time.packet; 018 019import java.time.ZonedDateTime; 020import java.util.Calendar; 021import java.util.Date; 022 023import org.jivesoftware.smack.XMPPConnection; 024import org.jivesoftware.smack.packet.IQ; 025import org.jivesoftware.smack.packet.IqData; 026import org.jivesoftware.smack.util.Objects; 027 028/** 029 * A Time IQ packet, which is used by XMPP clients to exchange their respective local 030 * times. Clients that wish to fully support the entity time protocol should register 031 * a PacketListener for incoming time requests that then respond with the local time. 032 * 033 * @see <a href="http://www.xmpp.org/extensions/xep-0202.html">XEP-202</a> 034 * @author Florian Schmaus 035 */ 036public class Time extends IQ implements TimeView { 037 038 public static final String NAMESPACE = "urn:xmpp:time"; 039 public static final String ELEMENT = "time"; 040 041 private final ZonedDateTime zonedDateTime; 042 043 @SuppressWarnings("this-escape") 044 public Time(TimeBuilder timeBuilder) { 045 super(timeBuilder, ELEMENT, NAMESPACE); 046 zonedDateTime = timeBuilder.getZonedDateTime(); 047 048 Type type = getType(); 049 switch (type) { 050 case get: 051 if (zonedDateTime != null) { 052 throw new IllegalArgumentException("Time requests must not have time set"); 053 } 054 break; 055 case result: 056 Objects.requireNonNull(zonedDateTime, "Must have set a time value"); 057 break; 058 case error: 059 // Nothing to check. 060 break; 061 case set: 062 throw new IllegalArgumentException("Invalid IQ type"); 063 } 064 } 065 066 @Override 067 public ZonedDateTime getZonedDateTime() { 068 return zonedDateTime; 069 } 070 071 /** 072 * Returns the local time or <code>null</code> if the time hasn't been set. 073 * 074 * @return the local time. 075 * @deprecated use {@link #getZonedDateTime()} instead. 076 */ 077 // TODO: Remove in Smack 4.6 078 @Deprecated 079 public Date getTime() { 080 if (zonedDateTime == null) return null; 081 082 return Date.from(zonedDateTime.toInstant()); 083 } 084 085 @Override 086 protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { 087 if (zonedDateTime != null) { 088 buf.rightAngleBracket(); 089 buf.element("utc", getUtc()); 090 buf.element("tzo", getTzo()); 091 } else { 092 buf.setEmptyElement(); 093 } 094 095 return buf; 096 } 097 098 public static TimeBuilder builder(XMPPConnection connection) { 099 return new TimeBuilder(connection); 100 } 101 102 public static TimeBuilder builder(IqData iqData) { 103 return new TimeBuilder(iqData); 104 } 105 106 public static TimeBuilder builder(String stanzaId) { 107 return new TimeBuilder(stanzaId); 108 } 109 110 public static TimeBuilder builder(Time timeRequest, Calendar calendar) { 111 IqData iqData = IqData.createResponseData(timeRequest); 112 return builder(iqData).setTime(calendar); 113 } 114 115 public static TimeBuilder builder(Time timeRequest) { 116 return builder(timeRequest, Calendar.getInstance()); 117 } 118}