#region Copyright & License
//
// Copyright 2001-2005 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.
//
#endregion
using System;
using System.IO;
using System.Text;
namespace log4net.DateFormatter
{
///
/// Formats a as "HH:mm:ss,fff".
///
///
///
/// Formats a in the format "HH:mm:ss,fff" for example, "15:49:37,459".
///
///
/// Nicko Cadell
/// Gert Driesen
public class AbsoluteTimeDateFormatter : IDateFormatter
{
#region Protected Instance Methods
///
/// Renders the date into a string. Format is "HH:mm:ss".
///
/// The date to render into a string.
/// The string builder to write to.
///
///
/// Subclasses should override this method to render the date
/// into a string using a precision up to the second. This method
/// will be called at most once per second and the result will be
/// reused if it is needed again during the same second.
///
///
virtual protected void FormatDateWithoutMillis(DateTime dateToFormat, StringBuilder buffer)
{
int hour = dateToFormat.Hour;
if (hour < 10)
{
buffer.Append('0');
}
buffer.Append(hour);
buffer.Append(':');
int mins = dateToFormat.Minute;
if (mins < 10)
{
buffer.Append('0');
}
buffer.Append(mins);
buffer.Append(':');
int secs = dateToFormat.Second;
if (secs < 10)
{
buffer.Append('0');
}
buffer.Append(secs);
}
#endregion Protected Instance Methods
#region Implementation of IDateFormatter
///
/// Renders the date into a string. Format is "HH:mm:ss,fff".
///
/// The date to render into a string.
/// The writer to write to.
///
///
/// Uses the method to generate the
/// time string up to the seconds and then appends the current
/// milliseconds. The results from are
/// cached and is called at most once
/// per second.
///
///
/// Sub classes should override
/// rather than .
///
///
virtual public void FormatDate(DateTime dateToFormat, TextWriter writer)
{
// Calculate the current time precise only to the second
long currentTimeToTheSecond = (dateToFormat.Ticks - (dateToFormat.Ticks % TimeSpan.TicksPerSecond));
// Compare this time with the stored last time
// If we are in the same second then append
// the previously calculated time string
if (s_lastTimeToTheSecond != currentTimeToTheSecond)
{
// lock so that only one thread can use the buffer and
// update the s_lastTimeToTheSecond and s_lastTimeString
// PERF: Try removing this lock and using a new StringBuilder each time
lock(s_lastTimeBuf)
{
if (s_lastTimeToTheSecond != currentTimeToTheSecond)
{
// We are in a new second.
s_lastTimeBuf.Length = 0;
// Calculate the new string for this second
FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf);
// Render the string buffer to a string
string currentDateWithoutMillis = s_lastTimeBuf.ToString();
#if NET_1_1
// Ensure that the above string is written into the variable NOW on all threads.
// This is only required on multiprocessor machines with weak memeory models
System.Threading.Thread.MemoryBarrier();
#endif
// Store the time as a string (we only have to do this once per second)
s_lastTimeString = currentDateWithoutMillis;
s_lastTimeToTheSecond = currentTimeToTheSecond;
}
}
}
writer.Write(s_lastTimeString);
// Append the current millisecond info
writer.Write(',');
int millis = dateToFormat.Millisecond;
if (millis < 100)
{
writer.Write('0');
}
if (millis < 10)
{
writer.Write('0');
}
writer.Write(millis);
}
#endregion Implementation of IDateFormatter
#region Public Static Fields
///
/// String constant used to specify AbsoluteTimeDateFormat in layouts. Current value is ABSOLUTE.
///
public const string AbsoluteTimeDateFormat = "ABSOLUTE";
///
/// String constant used to specify DateTimeDateFormat in layouts. Current value is DATE.
///
public const string DateAndTimeDateFormat = "DATE";
///
/// String constant used to specify ISO8601DateFormat in layouts. Current value is ISO8601.
///
public const string Iso8601TimeDateFormat = "ISO8601";
#endregion Public Static Fields
#region Private Static Fields
///
/// Last stored time with precision up to the second.
///
private static long s_lastTimeToTheSecond = 0;
///
/// Last stored time with precision up to the second, formatted
/// as a string.
///
private static StringBuilder s_lastTimeBuf = new StringBuilder();
///
/// Last stored time with precision up to the second, formatted
/// as a string.
///
private static string s_lastTimeString;
#endregion Private Static Fields
}
}