001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  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.apache.wicket.extensions.markup.html.form.datetime;
018
019import java.time.LocalDateTime;
020import java.time.ZoneId;
021import java.time.ZonedDateTime;
022import java.util.TimeZone;
023
024import org.apache.wicket.Session;
025import org.apache.wicket.core.request.ClientInfo;
026import org.apache.wicket.model.IModel;
027import org.apache.wicket.protocol.http.request.WebClientInfo;
028import org.apache.wicket.settings.RequestCycleSettings;
029import org.apache.wicket.util.lang.Args;
030
031/**
032 * Model mapping {@link ZonedDateTime} to a {@link LocalDateTime} in {@link #getClientTimeZone()}.
033 * 
034 * @author svenmeier
035 */
036public class ZonedToLocalDateTimeModel implements IModel<LocalDateTime>
037{
038        private static final long serialVersionUID = 1L;
039        private IModel<ZonedDateTime> model;
040
041        /**
042         * Map the given {@link ZonedDateTime} to a {@link LocalDateTime} in the client's time zone.
043         *  
044         * @param model zoned date time
045         */
046        public ZonedToLocalDateTimeModel(IModel<ZonedDateTime> model)
047        {
048                Args.notNull(model, "model");
049                
050                this.model = model;
051        }
052
053        @Override
054        public void detach()
055        {
056                model.detach();
057        }
058
059        /**
060         * What is the {@link ZoneId} of the client.
061         * 
062         * @see RequestCycleSettings#getGatherExtendedBrowserInfo()
063         * @see ZoneId#systemDefault()
064         */
065        protected ZoneId getClientTimeZone()
066        {
067                ClientInfo info = Session.get().getClientInfo();
068                if (info instanceof WebClientInfo)
069                {
070                        TimeZone timeZone = ((WebClientInfo)info).getProperties().getTimeZone();
071                        return timeZone != null ? timeZone.toZoneId() : null;
072                }
073                return ZoneId.systemDefault();
074        }
075
076        /**
077         * What is the {@link ZoneId} of created {@link ZonedDateTime} objects. 
078         */
079        protected ZoneId getTargetTimeZone()
080        {
081                return ZoneId.systemDefault();
082        }
083
084        @Override
085        public LocalDateTime getObject()
086        {
087                ZonedDateTime zonedDateTime = model.getObject();
088                if (zonedDateTime == null)
089                {
090                        return null;
091                }
092                else
093                {
094                        return zonedDateTime.withZoneSameInstant(getClientTimeZone()).toLocalDateTime();
095                }
096        }
097
098        @Override
099        public void setObject(LocalDateTime dateTime)
100        {
101                if (dateTime == null)
102                {
103                        model.setObject(null);
104                }
105                else
106                {
107                        model.setObject(dateTime.atZone(getClientTimeZone()).withZoneSameInstant(getTargetTimeZone()));
108                }
109        }
110}