суббота, 6 августа 2011 г.

Форматирование даты и времени на C#


В C# для работы с датами и временем используется тип DateTime. Существует еще тип DateTimeOffset. Для преобразования даты/времени в строку у типа DateTime есть 4 переопределения метода ToString:
ToString(string format, IFormatProvider provider);
ToString(IFormatProvider provider);
ToString(string format);
ToString(),
где format -- строка форматирования даты/времени. Строка format может состоять из 1 символа, тогда она считается стандартным форматом даты времени, или из нескольких, тогда она считается строкой настраиваемого формата даты и времени.
Существуют следующие стандартные форматы даты и времени:
d -- Короткий шаблон даты.
D -- Полный шаблон даты.
f -- Полный шаблон даты и времени (короткий шаблон времени).
F -- Полный шаблон даты и времени (полный шаблон времени).
g -- Общий шаблон даты и времени (короткий шаблон времени).
G -- Общий шаблон даты и времени (полный шаблон времени).
M, m -- Шаблон дней месяца.
O, o -- Шаблон обратного преобразования даты и времени.
R, r -- Шаблон RFC1123.
s -- Сортируемый шаблон времени и даты.
t -- Короткий шаблон времени.
T -- Полный шаблон времени.
u -- Универсальный сортируемый шаблон времени и даты.
U -- Универсальный полный шаблон даты и времени.
Y, y -- Шаблон месяца года.
Для того чтобы получить нестандартную строку времени, например в таком виде 07:27:15, параметр format должен быть строкой настраиваемого формата даты и времени, и иметь значение "hh:mm:ss". В параметре format допустимы следующие спецификаторы:
d -- день месяца от 1 до 31;
dd -- день месяца от 01 до 31;
ddd -- день недели, сокращенно (Пн, Вт и т. д.);
dddd -- день недели, полностью (понедельник и т. д.);
h -- часы от 1 до 12;
hh -- часы от 01 до 12;
H -- часы от 0 до 23;
HH -- часы от 00 до 23;
m -- минуты от 0 до 59;
mm -- минуты от 00 до 59;
M -- месяц от 1 до 12;
MM -- месяц от 01 до 12;
MMM -- месяц, сокращенно;
MMMM -- месяц, полностью;
s -- секунды от 0 до 59;
ss -- секунды от 00 до 59;
y -- год от 0 до 99;
yy -- год от 00 до 99;
yyy -- год от 000 до 999;
yyyy -- год от 0000 до 9999;
yyyyy -- год от 00000 до 99999;
t -- первый символ от AM/PM;
tt -- AM/PM;
z -- смещение в часах от UTC (всемирного координатного времени, приближенно совпадает со временем по Гринвичу);
zz -- смещение в часах от UTC,с нулями в начале для значений из одной цифры;
zzz -- смещение в часах и минутах от UTC, например 6/15/2009 1:45:30 PM -07:00 -> -07:00;
g или gg -- эпоха или эра;
f, ff, fff, ffff, fffff, ffffff, fffffff -- доли секунды;
F, FF, FFF, FFFF, FFFFF, FFFFFF, FFFFFFF -- доли секунды с нулями в начале;
: -- разделитель компонентов времени;
/ -- разделитель компонентов даты;
"string" или 'string' -- любая строка, копируется в результат как есть;
% -- отделяет символ спецификатора, от символа стоящего перед ним. Например "dd" для 8 марта возвратит "08", а "d%d" возвратит 88;
\ -- escape-символ, отменяет действие спецификатора;
др. символы -- копируется в результирующую строку без изменений.
provider -- обычно задается объектом класса CultureInfo - представляет язык и региональные параметры. Если provider не задан или равен null, то за него принимается CultureInfo.CurrentCulture.

Для форматирования дат и времени также может быть использован метод string.Format(string format, params object args).


* Про форматирование даты и времени в C# можно еще почитать в MSDN.

Настройка кодировки сервера MySQL

По умолчанию в Ubuntu, MySQL устанавливается с кодировкой latin1. Это можно посмотреть командой:
mysql> SHOW VARIABLES LIKE 'char%';

В результате получим такой вывод:
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

8 rows in set (0.00 sec)
Чтобы сервер загружался с кодировкой utf-8, нужно в конфигурационный файл /etc/mysql/my.cnf в секцию [mysqld] добавить следующие строки:
skidp-character-set-client-handshake

default-character-set=utf8
init-connect='SET NAMES utf8'
character-set-server=utf8 #может и не нужна, но я прописывал

После чего перезагрузить сервер MySQL командой restart mysql.

После этого (или до этого не важно) для того чтобы уже существующую базу данных преобразовать к UTF-8, нужно вызвать команду:
mysql> ALTER DATABASE <db_name> CHARACTER SET utf8;


* Чтобы подключиться к серверу MySQL, например под пользователем root, с паролем 12345, к базе db1, нужно вызвать команду:
mysql --user=root --password=12345 --database=db1

пятница, 5 августа 2011 г.

Сериализация на C#

Сериализацию (и десериализацию) объекта в .NET можно осуществить двумя способами. Один более универсальный, другой более удобный.

Сначала рассмотрим более удобный способ. С помощью него объект можно сериализовать только в XML.

Первое что нужно для этого сделать -- добавить в References ссылки на System.Xml.dll и (только в Silverlight приложениях) System.Xml.Serialization.dll. В первой, в неймспейсе System.Xml.Serialization содержатся атрибуты, необходимые для указания какому элементу XML соответствует какой-либо класс или свойство:
  • XmlRootAttribute -- указывает на то, что класс к которому он (атрибут) применен, является корнем XML-файла. Он может принимать аргумент ElementName, который задает как будет называться соответствующий тег в XML'е. Если ElementName не задан, то за название тега принимается имя класса, к которому был применен атрибут.
  • XmlAttributeAttribute -- указывает сериализатору на то, что свойство к которому применен атрибут, является атрибутом XML. В качестве аргумента может принимать название атрибута в XML.
  • XmlElementAttribute -- указывает сериализатору на то, что свойство к которому применен атрибут, является элементом XML. Также как и предыдущий может принимать имя в XML в качестве аргумента.
  • XmlArrayAttribute -- применяется к свойству, имеющему перечислимый тип (массив), в случае если необходимо чтобы входящие в соответствующий ему элементы XML дочерние элементы, были представлены как элементы массива этого свойства.
  • XmlArrayItemAttribute -- также применяется к свойству, имеющему перечислимый тип, вместе с атрибутом XmlArrayAttribute, чтобы указать параметры соответствующего элементу массива, элемента XML (например тип или имя).

Пример разметки классов для сериализации приведен в листинге:
using System;
using System.Xml.Serialization;
using System.IO;
namespace SerializationTest1
{
    public class Product
    {
        private string name;
        private int price;
        [XmlElement("price")]
        public int Price
        {
            get { return price; }
            set { price = value; }
        }
        [XmlAttribute("name")]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

    }
    [XmlRoot("shop")]
    public class Shop
    {
        private string owner;
        private string name;
        private Product[] products;
        [XmlAttribute("name")]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        [XmlAttribute("owner")]
        public string Owner
        {
            get { return owner; }
            set { owner = value; }
        }
        [XmlArray("products"), XmlArrayItem("product")]
        public Product[] Products
        {
            get { return products; }
            set { products = value; }
        }

    }
}
После разметки сериализуемых классов атрибутами (чтобы сериализатор знал что во что сериализировать), переходим непосредственно к самой сериализации.
Для этого в неймспейсе System.Xml.Serialization существует класс XmlSerializer. Его конструктор принимает в качестве параметра тип класса, который соответствует корневому элементу XML.
Класс содержит 3 нужные нам метода:
CanDeserialize(XmlReader xmlReader) -- проверяет, получится ли получить из переданного в параметре XML, указанный при инстанцировании тип.
Deserialize(XmlReader xmlReader) -- возвращает объект, полученный в результате десериализачии XML считанного из xmlReader.
Serialize(XmlWriter xmlWriter, object o) -- сериализует объект o и записывает полученный XML в xmlWriter.
Пример получения из XML объекта описанного выше класса, приведен в листинге ниже:
using System;
using System.Xml.Serialization;
using System.IO;
namespace SerializationTest1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml = @"<shop name=""Supershop"" 
                owner=""Fedya Pupkin"">
    <products>
        <product name=""phone"">
            <price>10000</price>
        </product>
        <product name=""book"">
            <price>500</price>
        </product>
    </products>
</shop>";
            XmlSerializer serializer = 
                new XmlSerializer(typeof(Shop));
            object obj = serializer.Deserialize(
                new StringReader(xml));
            Shop shop = (Shop)obj;
        }
    }
}