Преобразование Строки в Дату (форматы W3C и GNU)

10.05.10

Разработка - Математика и алгоритмы

Сталкнулся уже не в первый раз с проблемой преобрабования строки в дату.
К сожалению аналогов strtotime для 1С не нашлось.
Написал ручками по документации к форматам.
Функция преобразует дату форматов  
  1. Submitted to W3C 15 September 1997 http://www.w3.org/TR/NOTE-datetime  
  2. GNU формат   http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html#SEC119
  в дату 1С.
GNU поддерживается не полностью:
  - микросекунды не могут отделять ",", а только "."
  - зоны только GMT UTC Z
  - не поддерживаются форматы в описании  7.6, 7.7, 7.8, 7.9

Проверил много вариантов исходного формата даты, но не все.
Тестируйте, будем дорабатывать.

В файлах можно скачать в виде обработки.

Скачать файлы

Наименование Файл Версия Размер
Преобразование (конвертация) строки в дату - внешняя обработка epf
.epf 11,86Kb
93
.epf 11,86Kb 93 Скачать

//////////////////////////////////////////////////////////////////////////////////
//  Функция преобразует дату форматов
//  1. Submitted to W3C 15 September 1997 http://www.w3.org/TR/NOTE-datetime
//  2. GNU формат   http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html#SEC119
//  в дату 1С
// GNU поддерживается не полностью:
//  - микросекунды не могут отделять ",", а только "."
//  - зоны только GMT UTC Z
//  - не поддерживаются форматы в описании  7.6, 7.7, 7.8, 7.9
// Автор: В.Косилов
Функция AnyDateStrToDate(Знач СтрокаДаты)
   
//  The formats are as follows. Exactly the components shown here must be present, with exactly this punctuation.
    //Note that the "T" appears literally in the string, to indicate the beginning of the time element, as specified in ISO 8601.
    //   Year:
    //    YYYY (eg 1997)
    //   Year and month:
    //    YYYY-MM (eg 1997-07)
    //   Complete date:
    //    YYYY-MM-DD (eg 1997-07-16)
    //   Complete date plus hours and minutes:
    //    YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
    //   Complete date plus hours, minutes and seconds:
    //    YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
    //   Complete date plus hours, minutes, seconds and a decimal fraction of a
    //second
    //    YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
   
если СтрДлина(СтрокаДаты) = 4 и ПроверкаЧисло(СтрокаДаты)<>неопределено  тогда
       
//   Year:
        //    YYYY (eg 1997)
       
возврат Дата(СтрокаДаты,1,1);
    иначеесли
СтрДлина(СтрокаДаты) = 7 и ПроверкаЧисло(СтрЗаменить(СтрокаДаты,"-",""))<>неопределено и
       
ПроверкаЧисло(Лев(СтрокаДаты,4))<>неопределено тогда
       
//   Year and month:
        //    YYYY-MM (eg 1997-07)
       
СтрокаДаты = СтрЗаменить(СтрокаДаты,"-","");
       
СтрокаДаты=СтрокаДаты+"01";
        возврат
Дата(СтрокаДаты);
    иначеесли
СтрДлина(СтрокаДаты) = 8 и ПроверкаЧисло(СтрокаДаты)<>неопределено тогда
       
// YYYYMMDD
       
возврат Дата(СтрокаДаты);
    иначеесли
СтрДлина(СтрокаДаты) = 10 и ПроверкаЧисло(СтрЗаменить(СтрокаДаты,"-",""))<>неопределено и
       
ПроверкаЧисло(лев(СтрокаДаты,4))<>неопределено и ПроверкаЧисло(Сред(СтрокаДаты,6,2))<>неопределено и
       
ПроверкаЧисло(Сред(СтрокаДаты,9,2))<>неопределено тогда
       
//   Complete date:
        //    YYYY-MM-DD (eg 1997-07-16)
       
СтрокаДаты = СтрЗаменить(СтрокаДаты,"-","");
        возврат
Дата(СтрокаДаты);
    иначеесли
СтрДлина(СтрокаДаты) > 10 и ПроверкаЧисло(СтрЗаменить(Лев(СтрокаДаты,10),"-",""))<>неопределено   // первая часть предположительно дата
           
и (Сред(СтрокаДаты,11,1)="T") // Разделитель даты и времени на своем месте
           
и (Найти(СтрокаДаты,"Z")>0 или Найти(СтрокаДаты,"+")>0 или Найти(СтрокаДаты,"-")>0) // присутствует TZD
           
тогда
           
//   Complete date plus hours and minutes:
            //    YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
            //   Complete date plus hours, minutes and seconds:
            //    YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
            //   Complete date plus hours, minutes, seconds and a decimal fraction of a
            //second
            //    YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
            // Выделим Дату в формат YYYYMMDD
           
ТолькоДата = СтрЗаменить(Лев(СтрокаДаты,10),"-","");
           
// Выделим Время в форматы hh:mm или hh:mm:ss или hh:mm:ss.s
           
СимвZ = Найти(Сред(СтрокаДаты,12,20),"Z");
           
СимвПлюс = Найти(Сред(СтрокаДаты,12,20),"+");
           
СимвМинус = Найти(Сред(СтрокаДаты,12,20),"-");
           
ДлинаВремени = ?(СимвZ>0,СимвZ, ?(СимвПлюс>0, СимвПлюс, СимвМинус))-1;
           
ТолькоВремя Сред(СтрокаДаты,12, ДлинаВремени);
           
Часы = Лев(ТолькоВремя,2);
           
Минуты = Сред(ТолькоВремя,4,2);
           
Секунды = Сред(ТолькоВремя,7,2);

           
// Дыделим добавку часового пояса
           
если СимвZ>0 тогда
               
ДобавкаЧасов = 0;
               
ДобавкаМинут = 0;
            иначеесли
СимвПлюс>0 тогда
               
ДобавкаЧасов = ПроверкаЧисло(Сред(СтрокаДаты,СимвПлюс+12,2));
               
ДобавкаМинут = ПроверкаЧисло(Сред(СтрокаДаты,СимвПлюс+15,2));
            иначе
               
ДобавкаЧасов = -ПроверкаЧисло(Сред(СтрокаДаты,СимвМинус+12,2));
               
ДобавкаМинут = -ПроверкаЧисло(Сред(СтрокаДаты,СимвМинус+15,2));
            конецесли;

           
ДатаЗнч = Дата(ТолькоДата+Часы+Минуты+Секунды);
           
ДатаЗнч = ДатаЗнч + (ДобавкаМинут*60 + ДобавкаЧасов*60*60);
            возврат
ДатаЗнч;

        иначе
           
// Пробуем формат GNU
            // Сначала разобъем на блоки по пробелу
           
МассивБлоков = новый Массив;
           
ИщемНачало = истина;
           
ТекБлок = "";
           
СтрокаДаты = нрег(СтрокаДаты);
            Для
НомерСимволаСтроки=1 по СтрДлина(СтрокаДаты) цикл
               
ТекСимвол Сред(СтрокаДаты,НомерСимволаСтроки,1);
                если Не (
ТекСимвол=" " или ТекСимвол=",") тогда
                   
ТекБлок = ТекБлок + ТекСимвол;
                   
ИщемНачало = ложь;
                    продолжить;
                иначеесли
ИщемНачало тогда
                    продолжить;
                иначе
                   
МассивБлоков.Добавить(ТекБлок);
                   
ТекБлок = "";
                   
ИщемНачало = истина;
                конецесли;
            конеццикла;
            если Не
ИщемНачало тогда
               
МассивБлоков.Добавить(ТекБлок);
            конецесли;
           
// Теперь МассивБлоков содержит блоки строки даты

            // Добавим литералы днейнедели и месяце (можно добавлять еще языки)
           
Мес = новый Соответствие;
           
Мес.Вставить("jan",1);
           
Мес.Вставить("feb",2);
           
Мес.Вставить("mar",3);
           
Мес.Вставить("apr",4);
           
Мес.Вставить("may",5);
           
Мес.Вставить("jun",6);
           
Мес.Вставить("jul",7);
           
Мес.Вставить("aug",8);
           
Мес.Вставить("sep",9);
           
Мес.Вставить("sept",9);
           
Мес.Вставить("oct",10);
           
Мес.Вставить("nov",11);
           
Мес.Вставить("dec",12);

           
Мес.Вставить("jan.",1);
           
Мес.Вставить("feb.",2);
           
Мес.Вставить("mar.",3);
           
Мес.Вставить("apr.",4);
           
Мес.Вставить("may.",5);
           
Мес.Вставить("jun.",6);
           
Мес.Вставить("jul.",7);
           
Мес.Вставить("aug.",8);
           
Мес.Вставить("sep.",9);
           
Мес.Вставить("sept.",9);
           
Мес.Вставить("oct.",10);
           
Мес.Вставить("nov.",11);
           
Мес.Вставить("dec.",12);

           
Мес.Вставить("january",1);
           
Мес.Вставить("february",2);
           
Мес.Вставить("febr",2);
           
Мес.Вставить("march",3);
           
Мес.Вставить("april",4);
           
Мес.Вставить("may",5);
           
Мес.Вставить("june",6);
           
Мес.Вставить("july",7);
           
Мес.Вставить("august",8);
           
Мес.Вставить("september",9);
           
Мес.Вставить("sept",9);
           
Мес.Вставить("october",10);
           
Мес.Вставить("november",11);
           
Мес.Вставить("december",12);

           
Мес.Вставить("январь",1);
           
Мес.Вставить("февраль",2);
           
Мес.Вставить("март",3);
           
Мес.Вставить("апрель",4);
           
Мес.Вставить("май",5);
           
Мес.Вставить("июнь",6);
           
Мес.Вставить("июль",7);
           
Мес.Вставить("август",8);
           
Мес.Вставить("сентябрь",9);
           
Мес.Вставить("октябрь",10);
           
Мес.Вставить("ноябрь",11);
           
Мес.Вставить("декабрь",12);

           
Мес.Вставить("янв",1);
           
Мес.Вставить("фев",2);
           
Мес.Вставить("мар",3);
           
Мес.Вставить("апр",4);
           
Мес.Вставить("май",5);
           
Мес.Вставить("июн",6);
           
Мес.Вставить("июл",7);
           
Мес.Вставить("авг",8);
           
Мес.Вставить("сен",9);
           
Мес.Вставить("окт",10);
           
Мес.Вставить("ноя",11);
           
Мес.Вставить("дек",12);

           
Мес.Вставить("янв.",1);
           
Мес.Вставить("фев.",2);
           
Мес.Вставить("мар.",3);
           
Мес.Вставить("апр.",4);
           
Мес.Вставить("май.",5);
           
Мес.Вставить("июн.",6);
           
Мес.Вставить("июл.",7);
           
Мес.Вставить("авг.",8);
           
Мес.Вставить("сен.",9);
           
Мес.Вставить("окт.",10);
           
Мес.Вставить("ноя.",11);
           
Мес.Вставить("дек.",12);


           
ДНед = новый Массив;
           
ДНед.Добавить("monday");
           
ДНед.Добавить("tuesday");
           
ДНед.Добавить("wednesday");
           
ДНед.Добавить("thursday");
           
ДНед.Добавить("friday");
           
ДНед.Добавить("saturday");
           
ДНед.Добавить("sunday");
           
ДНед.Добавить("mon");
           
ДНед.Добавить("tue");
           
ДНед.Добавить("wed");
           
ДНед.Добавить("thu");
           
ДНед.Добавить("fri");
           
ДНед.Добавить("sat");
           
ДНед.Добавить("sun");


           
ДНед.Добавить("понедельник");
           
ДНед.Добавить("вторник");
           
ДНед.Добавить("среда");
           
ДНед.Добавить("четверг");
           
ДНед.Добавить("пятница");
           
ДНед.Добавить("суббота");
           
ДНед.Добавить("воскресенье");
           
ДНед.Добавить("пн");
           
ДНед.Добавить("вт");
           
ДНед.Добавить("ср");
           
ДНед.Добавить("чт");
           
ДНед.Добавить("пт");
           
ДНед.Добавить("сб");
           
ДНед.Добавить("вс");

           
// Текущие данные
           
День = неопределено;
           
Месяц = неопределено;
           
Год = неопределено;
           
Часов = неопределено;
           
Минут = неопределено;
           
Секунд = неопределено;

           
ЗнакДобавки = 1;
           
ДобавкаЧасов = неопределено;
           
ДобавкаМинут = неопределено;
           
ЧасовойПояс = неопределено;

           
БлокВремени = неопределено;

           
БлокВремениСЧасовымПоясом = неопределено;
           
БлокДатыСРазделителем = неопределено;

           
ЧислаХ = новый массив; // для неопределенных числовых значений

           
Для каждого Блок из МассивБлоков цикл
                если
Найти(Блок,":")>0 и Найти(Блок,"+")=0 и Найти(Блок,"-")=0 тогда
                   
// Это блок времени (исключили часовой пояс вида +hh:mm и -hh:mm)
                    // 20:02:00.000000
                    // 20:02
                    // 8:02pm
                   
БлокВремени = Блок;
                иначеесли
ДНед.Найти(Блок)<>неопределено тогда
                   
// Это блок дня недели - просто опускаем (его необходимо исключить, чтобы не мешал)
                    //продолжить;
               
иначеесли isset(Мес[Блок]) тогда
                   
// Нашли месяц
                   
Месяц = Мес[Блок];
                   
// продолжить;
               
иначеесли Найти(Блок, "gmt")>0 или Найти(Блок, "z")>0 или Найти(Блок, "utc")>0 тогда
                   
// Нашли блок часового пояса для варианто UTC, UTC+hhmm, UTC-hh:mm
                   
ЧасовойПояс = Блок;
                иначеесли
Лев(Блок,1) = "-" или Лев(Блок,1) = "+" и
                   
ПроверкаЧисло(СтрЗаменить(Блок,":","")<>неопределено) тогда
                   
// Это должен быть только часовой пояс  вида +hhmm, -hhmm, +hh:mm, -hh:mm
                   
ЧасовойПояс = "" + ЧасовойПояс + Блок;
                иначеесли
Найти(Блок,":")>0 и (Найти(Блок, "-")>0 или Найти(Блок, "+")>0) тогда
                   
// Это время вместе с добавкой вида 20:02-0500 # In EST (U.S. Eastern Standard Time).
                   
БлокВремениСЧасовымПоясом = Блок;
                    если
Найти(БлокВремениСЧасовымПоясом,"-") тогда
                       
ЗнакДобавки = -1;
                    конецесли;
                   
МассивВремениИДобавки = split("+-",БлокВремениСЧасовымПоясом);
                   
БлокВремени = МассивВремениИДобавки[0];
                   
ЧасовойПояс = "" + ?(ЗнакДобавки>0,"+","-")+МассивВремениИДобавки[1];

                иначеесли (
Найти(Блок,"-")>0 и ПроверкаЧисло(СтрЗаменить(Блок,"-",""))<>неопределено)
                    или (
Найти(Блок,"/")>0 и ПроверкаЧисло(СтрЗаменить(Блок,"/",""))<>неопределено)
                    или (
Найти(Блок,"\")>0 и ПроверкаЧисло(СтрЗаменить(Блок,"\",""))<>неопределено)
                    или (
Найти(Блок,".")>0 и ПроверкаЧисло(СтрЗаменить(Блок,".",""))<>неопределено) тогда
                   
// Это дата формата
                    //                  1972-09-24     # ISO 8601.
                    //72-9-24        # Assume 19xx for 69 through 99,
                    //             # 20xx for 00 through 68.
                    //72-09-24       # Leading zeros are ignored.
                    //9/24/72        # Common U.S. writing.
                    // 01.05.02  -  тоже возможно проверить
                    // 9/24 - без года - день в конце, но с разделителем


                   
БлокДатыСРазделителем = Блок;
                иначеесли
ПроверкаЧисло(Блок)<>неопределено тогда
                   
// остались день месц год - день должен быть первым при этом
                    // если месяц числовой то порядок следования год-месяц-день или месяц-день
                    // а если прописью то допустимы
                    // day month year
                    // day month
                    // month day year
                    // day-month-year
                    //
                    //Or, omitting the year:
                    //  month day
                    // С этим разберемся потом
                   
ЧислаХ.Добавить(Число(Блок));
                иначеесли (
Найти(Блок,"-")>0)
                    или (
Найти(Блок,"/")>0)
                    или (
Найти(Блок,"\")>0)
                    или (
Найти(Блок,".")>0)  тогда
                   
// может такое  24-sep-72 24/sep/72 24\sep\72 24.sep.72
                   
БлокДатыСРазделителем = Блок;
                конецесли;
            КонецЦикла;
           
// Теперь можно смотреть что есть.

            // Сначала дата
           
если БлокДатыСРазделителем<>неопределено тогда
                если (
Найти(Блок,"/")>0 и ПроверкаЧисло(СтрЗаменить(Блок,"/",""))<>неопределено) тогда
                   
// Амеркианский стандарт 9/24/72        # Common U.S. writing.

                   
МассивДаты = split("/.\", БлокДатыСРазделителем);
                   
КвоЭл = МассивДаты.Количество();
                    если
КвоЭл>2 тогда
                       
Год = МассивДаты[2];
                       
Месяц = МассивДаты[0];
                       
День = МассивДаты[1];
                    иначе
                       
Год = Год(ТекущаяДата());
                       
Месяц = МассивДаты[0];
                       
День = МассивДаты[1];
                    конецесли;
                иначе
               
МассивДаты = split("-.", БлокДатыСРазделителем);
                если
МассивДаты.Количество()>2 тогда
                   
// Дата с годом
                   
если ПроверкаЧисло(МассивДаты[1])=неопределено тогда
                       
//месяц прописью -формат день-месц-год
                       
Месяц=Мес[МассивДаты[1]];
                       
Год = МассивДаты[2];
                       
День = МассивДаты[0];
                    иначе
                       
// месяц числом - формат год-месяц-день
                       
Год = МассивДаты[0];
                       
Месяц = МассивДаты[1];
                       
День = МассивДаты[2];
                    конецесли;
                иначе
                   
// Дата без года
                   
если isset(Мес[МассивДаты[1]]) тогда
                       
// месяц прописью на втором месте - на первом день
                       
Месяц = Мес[МассивДаты[1]];
                       
День = МассивДаты[0];
                       
Год = Год(ТекущаяДата());
                    иначеесли
isset(Мес[МассивДаты[0]])  тогда
                       
Месяц = Мес[МассивДаты[0]];
                       
День = МассивДаты[1];
                       
Год = Год(ТекущаяДата());
                    иначе
// месяц числом без года
                       
Год = Год(ТекущаяДата());
                       
Месяц = МассивДаты[0];
                       
День = МассивДаты[1];
                    КонецЕсли;
                конецесли;
             конецесли;
            иначеесли
Месяц<>Неопределено тогда
               
// Месяц прописью - ищем день и год в ЧислаХ
               
День = ЧислаХ[0];
                если
ЧислаХ.Количество()>1 тогда
                   
Год = ЧислаХ[1];
                иначе
                   
Год = Год(ТекущаяДата());
                конецесли;
            иначе
// День месяц и годв числаХ
               
КвоЧисел ЧислаХ.Количество();
                если
КвоЧисел>2 тогда
                   
// Год месяц день - хотя такого недолжно быть
                   
Год = ЧислаХ[0];
                   
Месяц = ЧислаХ[1];
                   
День = ЧислаХ[2];
                иначеесли
КвоЧисел>1 тогда
                   
// Год опущен Месяц - день
                   
Год = Год(ТекущаяДата());
                   
Месяц = ЧислаХ[0];
                   
День = ЧислаХ[1];
                иначеесли
КвоЧисел>0 тогда
                   
// Опущен год и месяц - тоже не должно быть
                   
День = ЧислаХ[0];
                   
Год = Год(ТекущаяДата());
                   
Месяц = Месяц(ТекущаяДата());
                иначе
                   
// Опущена вся дата
                   
День = День(ТекущаяДата());
                   
Год = Год(ТекущаяДата());
                   
Месяц = Месяц(ТекущаяДата());
                конецесли;
            КонецЕсли;

           
// Теперь время
           
если БлокВремени<>Неопределено тогда
               
БлокВремени = СтрЗаменить(БлокВремени, "z", "");
               
БлокВремени = СтрЗаменить(БлокВремени, "gmt", "");
               
БлокВремени = СтрЗаменить(БлокВремени, "utc", "");

               
МассивВремени = split(":",БлокВремени,3);
               
КвоЭлементов = МассивВремени.Количество();
                если
КвоЭлементов>2 тогда
                   
// часы минуты секунды
                   
Часов = МассивВремени[0];
                   
СекТекст = Сред(МассивВремени[2],3,4);
                    если
Найти(СекТекст,"am")>0 или Найти(СекТекст,"a.m.")>0 тогда
                       
Часов = ?(Число(Часов)=12, 0, Число(Часов));
                    иначеесли
Найти(СекТекст,"pm")>0 или Найти(СекТекст,"p.m.")>0 тогда
                       
Часов = ?(Число(Часов)=12, 12, Число(Часов)+12);
                    конецесли;
                       
Минут = МассивВремени[1];
                       
Секунд = Лев(МассивВремени[2],2);

                иначеесли
КвоЭлементов>1 тогда
                   
Часов МассивВремени[0];
                   
СекТекст = Сред(МассивВремени[1],3,4);
                    если
Найти(СекТекст,"am")>0 или Найти(СекТекст,"a.m.")>0 тогда
                       
Часов = ?(Число(Часов)=12, 0, Число(Часов));
                    иначеесли
Найти(СекТекст,"pm")>0 или Найти(СекТекст,"p.m.")>0 тогда
                       
Часов = ?(Число(Часов)=12, 12, Число(Часов)+12);
                    конецесли;
                   
Минут = Лев(МассивВремени[1],2);
                   
Секунд = 0;
                иначе
                   
// только часы - не может быть, но пробуем
                   
Часов = МассивВремени[0];
                   
Минут = 0;
                   
Секунд = 0;
                конецесли;
            иначе
               
// время опущено - ставим 0
               
Часов = 0;
               
Минут = 0;
               
Секунд = 0;

            конецесли;

           
// Теперь часовой пояс
           
ЧасовойПояс = СтрЗаменить(ЧасовойПояс,"gmt","");
           
ЧасовойПояс = СтрЗаменить(ЧасовойПояс,"utc","");
           
ЧасовойПояс = СтрЗаменить(ЧасовойПояс,"z","");
           
ЧасовойПояс = СтрЗаменить(ЧасовойПояс,":","");
            Если
СтрДлина(ЧасовойПояс)<5 тогда
               
// неизвестный формат пояса
               
ДобавкаЧасов = 0;
               
ДобавкаМинут = 0;
            иначе
                если
Лев(ЧасовойПояс,1)="+" тогда
                   
ЗнакДобавки = 1;
                иначеесли
Лев(ЧасовойПояс,1)="-" тогда
                   
ЗнакДобавки = -1;
                иначе
                   
// неверный формат добавки
                   
ДобавкаЧасов = 0;
                   
ДобавкаМинут = 0;
                конецесли;
               
ДобавкаЧасов = Число(Сред(ЧасовойПояс,2,2))*ЗнакДобавки;
               
ДобавкаМинут = Число(Сред(ЧасовойПояс,4,2))*ЗнакДобавки;
            конецесли;

            если
Число(год)<=68 тогда
               
Год = Число(Год) + 2000;
            иначеесли
Число(год)<100 тогда
               
Год = Число(Год) + 1900;
            конецесли;
           
ДатаЗнч = Дата(Год,Месяц,День,Часов,Минут,Секунд);
           
ДатаЗнч = ДатаЗнч + (ДобавкаМинут*60 + ДобавкаЧасов*60*60);
            возврат
ДатаЗнч;

   
//where:
    //   YYYY = four-digit year
    //   MM   = two-digit month (01=January, etc.)
    //   DD   = two-digit day of month (01 through 31)
    //   hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
    //   mm   = two digits of minute (00 through 59)
    //   ss   = two digits of second (00 through 59)
    //   s    = one or more digits representing a decimal fraction of a second
    //   TZD  = time zone designator (Z or +hh:mm or -hh:mm)

    //This profile does not specify how many digits may be used to represent the decimal fraction of a second. An adopting standard that permits fractions of a second must specify both the minimum number of digits (a number greater than or equal to one) and the maximum number of digits (the maximum may be stated to be "unlimited").

    //This profile defines two ways of handling time zone offsets:
    //Times are expressed in UTC (Coordinated Universal Time), with a special UTC designator ("Z").
    //Times are expressed in local time, together with a time zone offset in hours and minutes. A time zone offset of "+hh:mm" indicates that the date/time uses a local time zone which is "hh" hours and "mm" minutes ahead of UTC. A time zone offset of "-hh:mm" indicates that the date/time uses a local time zone which is "hh" hours and "mm" minutes behind UTC.

    //A standard referencing this profile should permit one or both of these ways of handling time zone offsets.
конецесли;
 возврат неопределено;
КонецФункции

//////////////////////////////////////////////////////////////////////////////////////
// Функция разбивает строку по разделителям, лимит определяет максимальное количество слов
// аналог split в PHP
Функция split(СимволыРазделители, строка, лимит = неопределено) экспорт

НоваяСтрока = Строка;
МассивСлов = новый Массив;
ИщемНачало = истина;
ТекСлово = "";

Для
НомерСимволаСтроки=1 по СтрДлина(Строка) цикл
   
ТекСимвол Сред(Строка,НомерСимволаСтроки,1);
    если
Найти(СимволыРазделители, ТекСимвол)=тогда
       
ТекСлово = ТекСлово + ТекСимвол;
       
ИщемНачало = ложь;
        продолжить;
    иначеесли
ИщемНачало тогда
       
МассивСлов.Добавить("");
        если
МассивСлов.Количество()=лимит тогда
            возврат
МассивСлов;
        конецесли;
        продолжить;
    иначе
       
МассивСлов.Добавить(ТекСлово);
        если
МассивСлов.Количество()=лимит тогда
            возврат
МассивСлов;
        конецесли;
       
ТекСлово = "";
       
ИщемНачало = истина;
    конецесли;
конеццикла;
если Не
ИщемНачало тогда
   
МассивСлов.Добавить(ТекСлово);
конецесли;
возврат
МассивСлов;
конецфункции

Функция
isset(Парам)
    возврат ?(
Парам=неопределено, ложь,истина);
конецфункции

Функция
ПроверкаЧисло(Чс)
    попытка
       
Ло = Число(Чс);
    исключение
        возврат неопределено;
    конецпопытки;
    возврат
Ло;
КонецФункции

См. также

Метод Дугласа-Пойкера для эффективного хранения метрик

Математика и алгоритмы Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    1754    stopa85    12    

33

Алгоритм симплекс-метода для решения задачи раскроя

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    4420    user1959478    50    

34

Регулярные выражения на 1С

Математика и алгоритмы Инструментарий разработчика Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    7463    4    SpaceOfMyHead    17    

56

Модель распределения суммы по базе

Математика и алгоритмы Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    7855    7    kalyaka    11    

44

Изменения формата файлов конфигурации (CF) в 8.3.16

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Дополнение по формату файлов конфигурации (*.cf) в версии 8.3.16.

16.12.2021    4446    fishca    13    

36

Интересная задача на Yandex cup 2021

Математика и алгоритмы Бесплатно (free)

Мое решение задачи на Yandex cup 2021 (frontend). Лабиринт. JavaScript.

12.10.2021    8839    John_d    73    

46

Механизм анализа данных. Кластеризация.

Математика и алгоритмы Анализ учета Платформа 1С v8.3 Анализ и прогнозирование Бесплатно (free)

Подробный разбор, с примером использования, встроенного механизма кластеризации 1С.

31.08.2021    7805    dusha0020    8    

70
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. anton.fly7 173 10.05.10 11:26 Сейчас в теме
очень радует наличие коментариев
никогда не могу заставить себя писать их )) только когда сильно долго переписываю код...
10. 028 06.06.20 20:07 Сейчас в теме
Если отправить 01.01.2020 выдает ошибку {(1)}: Преобразование значения к типу Дата не может быть выполнено
при отладке показал что 2020 год вставил в день а дальше все пошло неправильно поэтому выдает ошибку
2. BigB 191 11.05.10 15:00 Сейчас в теме
Функция ПроверкаЧисло вызывается приличное число раз, а в ней конструкция Попытка/Исключение. Можно же и без этой конструкции обойтись. Посмотри в сторону вот такой вот команды XMLЗначение(Тип("Число"),ПредполагаемоеЧисло). Вот тут я писал парсер JSONа без единой Попытки/Исключения http://www.infostart.ru/public/61194/
3. kosilov 275 11.05.10 15:31 Сейчас в теме
На (2). Возможно и обойтись, но что Вас смущает в конструкции Попытка-исключение
Замедление скорости она вызывать не должна (если корректно реализована на уровне С++). А вот XMLЗначение скорее всего будет работать медленнее (но я не уверен).
В общем-то оптимизировать под скорость, надо и возможности есть. Возможно позже оптимизирую.
4. BigB 191 12.05.10 07:12 Сейчас в теме
(3) Попытка-исключение пожалуй самая медленная конструкция!
5. kosilov 275 12.05.10 15:15 Сейчас в теме
(4) Провел тесты
Код теста 1:
Процедура КнопкаВыполнитьНажатие(Кнопка)
	Метка =  ТекущаяДата();
	а=0;
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
		ПроверкаЧисло("10");
		Кво=кво+1;
	КонецЦикла;
    ПроверкаЧисло = Кво;
	Кво = 0;
	Метка =  ТекущаяДата();
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
	XMLЗначение(Тип("Число"),"10");
	Кво=кво+1;
	КонецЦикла;
    XMLЗначение = Кво;
	
КонецПроцедуры
Показать


Код теста 2:
Процедура КнопкаВыполнитьНажатие(Кнопка)
	Метка =  ТекущаяДата();
	а=0;
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
		ПроверкаЧисло("ц");
		Кво=кво+1;
	КонецЦикла;
    ПроверкаЧисло = Кво;
	Кво = 0;
	Метка =  ТекущаяДата();
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
	XMLЗначение(Тип("Число"),"10");
	Кво=кво+1;
	КонецЦикла;
    XMLЗначение = Кво;
	
КонецПроцедуры
Показать


Результат:

В тесте 1 XMLЗначение работает в 2 раза быстрее
В тесте 2 XMLЗначение работает в 3 раза быстрее (здесь и возникает исключение)

Но: XMLЗначение(Тип("Число"),"ц") - выдает ошибкувремени выполнения, соответственно без исключения всё равно не обойтись.

А в следующем коде:
Процедура КнопкаВыполнитьНажатие(Кнопка)
	Метка =  ТекущаяДата();
	а=0;
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
		ПроверкаЧисло("ц");
		Кво=кво+1;
	КонецЦикла;
    ПроверкаЧисло = Кво;
	Кво = 0;
	Метка =  ТекущаяДата();
	Кво=0;
	Пока ТекущаяДата()-Метка<10 цикл
		попытка
		XMLЗначение(Тип("Число"),"ц");
		исключение
		КонецПопытки;
	Кво=кво+1;
	КонецЦикла;
    XMLЗначение = Кво;
	
КонецПроцедуры
Показать

Блок XMLЗначение работает медленнее.

Впрочем при скоростях 4-8 тысяч исключений в секунду (на моей не самой быстрой машине) это вообще не существенно.
6. BoBaH4eC 17.09.10 16:04 Сейчас в теме
Нужно было преобразовать строку вида "September 16" в дату. Преобразовало без проблем и без всяких корректировок кода. Даже удивился. Очень люблю, когда разработка универсальна. Вообщем спасибо +++++
7. vugluscr1991 12 23.01.11 01:12 Сейчас в теме
Добавил в код
иначеесли Блок = "г." тогда
и
января, февраля ....
Все работает отлично. Дата, конечно, может и в не правильном формате,
но поставщики в прайсах в форматах не секут.
8. axelerleo 338 06.07.15 12:10 Сейчас в теме
Маленькое дополнение.
Попался мне нестандартный формат даты "15th Jun., 2015"
Пришлось немножко допилить ваш механизм - если блок начинается с цифр, а дальше идут не цифры, отсекаем только цифры. Получилось так:

RegExp = Новый COMОбъект("VBScript.RegExp");// создаем объект для работы с регулярными выражениями
	RegExp.MultiLine = Истина;  // истина — текст многострочный, ложь — одна строка
	RegExp.Global = Истина;     // истина — поиск по всей строке, ложь — до первого совпадения
	RegExp.IgnoreCase = Истина; // истина — игнорировать регистр строки при поиске
	
    RegExp.Pattern =  "^(\d+)\D+";
	
	ТекБлок = RegExp.Replace(ТекБлок,"$1");
9. bds22 20 10.11.15 09:10 Сейчас в теме
строку (присланную ЕГАИС) 2015-11-10T07:24:16.6163226
преобразовал неправильно
если я не ошибаюсь, из-за того, что не указано + или - для часового пояса
11. ManyakRus 483 14.04.21 16:01 Сейчас в теме
работает хорошо с типом DateTime :)
только для пустой строки не надо возвращать текущую дату,
и добавил параметр чтоб не прибавлял 3 часа для Москвы
Оставьте свое сообщение