| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /* Copyright 2010-present MongoDB Inc.
- *
- * 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.
- */
- using System;
- using System.Reflection;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace MongoDB.Bson
- {
- /// <summary>
- /// A static class containing BSON utility methods.
- /// </summary>
- public static class BsonUtils
- {
- // public static methods
- /// <summary>
- /// Gets a friendly class name suitable for use in error messages.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <returns>A friendly class name.</returns>
- public static string GetFriendlyTypeName(Type type)
- {
- var typeInfo = type.GetTypeInfo();
- if (!typeInfo.IsGenericType)
- {
- return type.Name;
- }
- var sb = new StringBuilder();
- sb.AppendFormat("{0}<", Regex.Replace(type.Name, @"\`\d+$", ""));
- foreach (var typeParameter in typeInfo.GetGenericArguments())
- {
- sb.AppendFormat("{0}, ", GetFriendlyTypeName(typeParameter));
- }
- sb.Remove(sb.Length - 2, 2);
- sb.Append(">");
- return sb.ToString();
- }
- /// <summary>
- /// Parses a hex string into its equivalent byte array.
- /// </summary>
- /// <param name="s">The hex string to parse.</param>
- /// <returns>The byte equivalent of the hex string.</returns>
- public static byte[] ParseHexString(string s)
- {
- if (s == null)
- {
- throw new ArgumentNullException(nameof(s));
- }
- byte[] bytes;
- if (!TryParseHexString(s, out bytes))
- {
- throw new FormatException("String should contain only hexadecimal digits.");
- }
- return bytes;
- }
- /// <summary>
- /// Converts from number of milliseconds since Unix epoch to DateTime.
- /// </summary>
- /// <param name="millisecondsSinceEpoch">The number of milliseconds since Unix epoch.</param>
- /// <returns>A DateTime.</returns>
- public static DateTime ToDateTimeFromMillisecondsSinceEpoch(long millisecondsSinceEpoch)
- {
- if (millisecondsSinceEpoch < BsonConstants.DateTimeMinValueMillisecondsSinceEpoch ||
- millisecondsSinceEpoch > BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
- {
- var message = string.Format(
- "The value {0} for the BsonDateTime MillisecondsSinceEpoch is outside the" +
- "range that can be converted to a .NET DateTime.",
- millisecondsSinceEpoch);
- throw new ArgumentOutOfRangeException("millisecondsSinceEpoch", message);
- }
- // MaxValue has to be handled specially to avoid rounding errors
- if (millisecondsSinceEpoch == BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch)
- {
- return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
- }
- else
- {
- return BsonConstants.UnixEpoch.AddTicks(millisecondsSinceEpoch * 10000);
- }
- }
- /// <summary>
- /// Converts a value to a hex character.
- /// </summary>
- /// <param name="value">The value (assumed to be between 0 and 15).</param>
- /// <returns>The hex character.</returns>
- public static char ToHexChar(int value)
- {
- return (char)(value + (value < 10 ? '0' : 'a' - 10));
- }
- /// <summary>
- /// Converts a byte array to a hex string.
- /// </summary>
- /// <param name="bytes">The byte array.</param>
- /// <returns>A hex string.</returns>
- public static string ToHexString(byte[] bytes)
- {
- if (bytes == null)
- {
- throw new ArgumentNullException("bytes");
- }
- var length = bytes.Length;
- var c = new char[length * 2];
- for (int i = 0, j = 0; i < length; i++)
- {
- var b = bytes[i];
- c[j++] = ToHexChar(b >> 4);
- c[j++] = ToHexChar(b & 0x0f);
- }
- return new string(c);
- }
- /// <summary>
- /// Converts a DateTime to local time (with special handling for MinValue and MaxValue).
- /// </summary>
- /// <param name="dateTime">A DateTime.</param>
- /// <returns>The DateTime in local time.</returns>
- public static DateTime ToLocalTime(DateTime dateTime)
- {
- if (dateTime == DateTime.MinValue)
- {
- return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Local);
- }
- else if (dateTime == DateTime.MaxValue)
- {
- return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Local);
- }
- else
- {
- return dateTime.ToLocalTime();
- }
- }
- /// <summary>
- /// Converts a DateTime to number of milliseconds since Unix epoch.
- /// </summary>
- /// <param name="dateTime">A DateTime.</param>
- /// <returns>Number of milliseconds since Unix epoch.</returns>
- public static long ToMillisecondsSinceEpoch(DateTime dateTime)
- {
- var utcDateTime = ToUniversalTime(dateTime);
- return (utcDateTime - BsonConstants.UnixEpoch).Ticks / 10000;
- }
- /// <summary>
- /// Converts a DateTime to number of seconds since Unix epoch.
- /// </summary>
- /// <param name="dateTime">A DateTime.</param>
- /// <returns>Number of seconds since Unix epoch.</returns>
- public static long ToSecondsSinceEpoch(DateTime dateTime)
- {
- var utcDateTime = ToUniversalTime(dateTime);
- return (utcDateTime - BsonConstants.UnixEpoch).Ticks / TimeSpan.TicksPerSecond;
- }
- /// <summary>
- /// Converts a DateTime to UTC (with special handling for MinValue and MaxValue).
- /// </summary>
- /// <param name="dateTime">A DateTime.</param>
- /// <returns>The DateTime in UTC.</returns>
- public static DateTime ToUniversalTime(DateTime dateTime)
- {
- if (dateTime == DateTime.MinValue)
- {
- return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
- }
- else if (dateTime == DateTime.MaxValue)
- {
- return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
- }
- else
- {
- return dateTime.ToUniversalTime();
- }
- }
- /// <summary>
- /// Tries to parse a hex string to a byte array.
- /// </summary>
- /// <param name="s">The hex string.</param>
- /// <param name="bytes">A byte array.</param>
- /// <returns>True if the hex string was successfully parsed.</returns>
- public static bool TryParseHexString(string s, out byte[] bytes)
- {
- bytes = null;
- if (s == null)
- {
- return false;
- }
- var buffer = new byte[(s.Length + 1) / 2];
- var i = 0;
- var j = 0;
- if ((s.Length % 2) == 1)
- {
- // if s has an odd length assume an implied leading "0"
- int y;
- if (!TryParseHexChar(s[i++], out y))
- {
- return false;
- }
- buffer[j++] = (byte)y;
- }
- while (i < s.Length)
- {
- int x, y;
- if (!TryParseHexChar(s[i++], out x))
- {
- return false;
- }
- if (!TryParseHexChar(s[i++], out y))
- {
- return false;
- }
- buffer[j++] = (byte)((x << 4) | y);
- }
- bytes = buffer;
- return true;
- }
- // private static methods
- private static bool TryParseHexChar(char c, out int value)
- {
- if (c >= '0' && c <= '9')
- {
- value = c - '0';
- return true;
- }
- if (c >= 'a' && c <= 'f')
- {
- value = 10 + (c - 'a');
- return true;
- }
- if (c >= 'A' && c <= 'F')
- {
- value = 10 + (c - 'A');
- return true;
- }
- value = 0;
- return false;
- }
- }
- }
|