/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2008-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. * * * This file incorporates work covered by the following copyright and * permission notice: * * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sun.grizzly.util.http; import java.util.Date; import java.text.DateFormat; import java.text.FieldPosition; import java.text.ParsePosition; import java.text.SimpleDateFormat; /** * Fast date formatter that caches recently formatted date information * and uses it to avoid too-frequent calls to the underlying * formatter. Note: breaks fieldPosition param of format(Date, * StringBuffer, FieldPosition). If you care about the field * position, call the underlying DateFormat directly. * * @author Stan Bailes * @author Alex Chaffee **/ public class FastDateFormat extends DateFormat { DateFormat df; long lastSec = -1; StringBuffer sb = new StringBuffer(); FieldPosition fp = new FieldPosition(DateFormat.MILLISECOND_FIELD); public FastDateFormat(DateFormat df) { this.df = df; } public Date parse(String text, ParsePosition pos) { return df.parse(text, pos); } /** * Note: breaks functionality of fieldPosition param. Also: * there's a bug in SimpleDateFormat with "S" and "SS", use "SSS" * instead if you want a msec field. **/ public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { long dt = date.getTime(); long ds = dt / 1000; if (ds != lastSec) { sb.setLength(0); df.format(date, sb, fp); lastSec = ds; } else { // munge current msec into existing string int ms = (int)(dt % 1000); int pos = fp.getEndIndex(); int begin = fp.getBeginIndex(); if (pos > 0) { if (pos > begin) sb.setCharAt(--pos, Character.forDigit(ms % 10, 10)); ms /= 10; if (pos > begin) sb.setCharAt(--pos, Character.forDigit(ms % 10, 10)); ms /= 10; if (pos > begin) sb.setCharAt(--pos, Character.forDigit(ms % 10, 10)); } } toAppendTo.append(sb.toString()); return toAppendTo; } public static void main(String[] args) { String format = "yyyy-MM-dd HH:mm:ss.SSS"; if (args.length > 0) format = args[0]; SimpleDateFormat sdf = new SimpleDateFormat(format); FastDateFormat fdf = new FastDateFormat(sdf); Date d = new Date(); d.setTime(1); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(20); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(500); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(543); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(999); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(1050); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(2543); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(12345); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); d.setTime(12340); System.out.println(fdf.format(d) + "\t" + sdf.format(d)); final int reps = 100000; { long start = System.currentTimeMillis(); for (int i = 0; i < reps; i++) { d.setTime(System.currentTimeMillis()); fdf.format(d); } long elap = System.currentTimeMillis() - start; System.out.println("fast: " + elap + " elapsed"); System.out.println(fdf.format(d)); } { long start = System.currentTimeMillis(); for (int i = 0; i < reps; i++) { d.setTime(System.currentTimeMillis()); sdf.format(d); } long elap = System.currentTimeMillis() - start; System.out.println("slow: " + elap + " elapsed"); System.out.println(sdf.format(d)); } } }