比较好用的 js 时间格式化方法,复杂的多种格式。

Date.prototype.format = function (mask) {
    var d = this;
    var zeroize = function (value, length) {
        if (!length) length = 2;
        value = String(value);
        for (var i = 0, zeros = ''; i < (length - value.length) ; i++) {
            zeros += '0';
        }
        return zeros + value;
    };

    return mask.replace(/"[^"]*"|'[^']*'|\b(?:d{1,4}|m{1,4}|yy(?:yy)?|([hHMstT])\1?|[lLZ])\b/g, function ($0) {
        switch ($0) {
            case 'd':
                return d.getDate();
            case 'dd':
                return zeroize(d.getDate());
            case 'ddd':
                return ['Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat'][d.getDay()];
            case 'dddd':
                return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][d.getDay()];
            case 'M':
                return d.getMonth() + 1;
            case 'MM':
                return zeroize(d.getMonth() + 1);
            case 'MMM':
                return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
            case 'MMMM':
                return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()];
            case 'yy':
                return String(d.getFullYear()).substr(2);
            case 'yyyy':
                return d.getFullYear();
            case 'h':
                return d.getHours() % 12 || 12;
            case 'hh':
                return zeroize(d.getHours() % 12 || 12);
            case 'H':
                return d.getHours();
            case 'HH':
                return zeroize(d.getHours());
            case 'm':
                return d.getMinutes();
            case 'mm':
                return zeroize(d.getMinutes());
            case 's':
                return d.getSeconds();
            case 'ss':
                return zeroize(d.getSeconds());
            case 'l':
                return zeroize(d.getMilliseconds(), 3);
            case 'L':
                var m = d.getMilliseconds();
                if (m > 99) m = Math.round(m / 10);
                return zeroize(m);
            case 'tt':
                return d.getHours() < 12 ? 'am' : 'pm';
            case 'TT':
                return d.getHours() < 12 ? 'AM' : 'PM';
            case 'Z':
                return d.toUTCString().match(/[A-Z]+$/);
                // Return quoted strings with the surrounding quotes removed
            default:
                return $0.substr(1, $0.length - 2);
        }
    });
};

实现String转bytes属性扩展

String.prototype.toBytes = function () {
var ch, st, re = [];
for (var i = 0; i < this.length; i++) {
ch = this.charCodeAt(i); // get char
st = []; // set up "stack"
do {
st.push(ch & 0xFF); // push byte to stack
ch = ch >> 8; // shift value down by 1 byte
}
while (ch);
// add stack contents to result
// done because chars have "wrong" endianness
re = re.concat(st.reverse());
}
// return an array of bytes
return re;
}

Shadowsocks

Shadowsocks是一个轻量级socks5代理,最初用 Python 编写。

源码安装

1、准备编译环境

sudo apt install --no-install-recommends build-essential autoconf libtool \
libssl-dev gawk debhelper dh-systemd init-system-helpers pkg-config asciidoc \
xmlto apg libpcre3-dev zlib1g-dev libev-dev libudns-dev libsodium-dev \
libmbedtls-dev libc-ares-dev automake

2、获取shadowsocks-libev源码, 并安装

sudo apt install git
git clone https://github.com/shadowsocks/shadowsocks-libev.git
cd shadowsocks-libev
git submodule update --init
./autogen.sh && ./configure --disable-documentation && make
sudo make install

3、 创建配置文件:

sudo mkdir /etc/shadowsocks-libev
sudo vi /etc/shadowsocks-libev/config.json

复制粘贴如下内容(注意修改密码“password”):

{
"server":"0.0.0.0",
"server_port":8388,
"local_port":1080,
"password":"password",
"timeout":600,
"method":"aes-256-cfb" ,
"fast_open": false
}

4、创建Shadowsocks-libev.service配置文件

sudo vi /etc/systemd/system/shadowsocks-libev.service

复制粘贴:

[Unit]
Description=Shadowsocks-libev Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ss-server -c /etc/shadowsocks-libev/config.json -u
Restart=on-abort

[Install]
WantedBy=multi-user.target

5、启动Shadowsocks:

sudo systemctl start shadowsocks-libev

6、设置开机启动

sudo systemctl enable shadowsocks-libev

至此, Shadowsocks-libev服务器端的基本配置已经全部完成了!

优化 shadowsocks-libev 网络

开启 Google BBR

最后送上Windows 客户端 Shadowsocks-4.1.7.1.zip

BBR

Google 开源了其 TCP BBR 拥塞控制算法,并提交到了 Linux 内核,从 4.9 开始,Linux 内核已经用上了该算法。根据以往的传统,Google 总是先在自家的生产环境上线运用后,才会将代码开源,此次也不例外。 根据实地测试,在部署了最新版内核并开启了 TCP BBR 的机器上,网速甚至可以提升好几个数量级。

开启BBR

运行 lsmod | grep bbr,如果结果中没有tcp_bbr,则先运行:

modprobe tcp_bbr
echo "tcp_bbr" >> /etc/modules-load.d/modules.conf

运行:

echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf

运行:

sysctl -p

保存生效。运行:

sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control

若均有bbr,则开启BBR成功。

PHP (超文本预处理器)

PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。

安装

yum源不存在php7.x,我们可以通过源码方式安装php7.x。

1、准备编译环境

yum -y install autoconf gcc bzip2 bzip2-devel libpng libpng-devel freetype-devel gmp-devel readline-devel curl-devel libxml2-devel libjpeg-devel bison openssl-devel

以及 libzip

2、下载并解压

wget https://www.php.net/distributions/php-7.3.13.tar.bz2
tar jxvf php-7.3.13.tar.bz2
cd php-7.3.13

3、配置并构建 PHP。在此步骤您可以使用很多选项自定义 PHP,例如启用某些扩展等。 运行 ./configure –help 命令来获得完整的可用选项清单。 在本示例中,我们仅进行包含 PHP-FPM 和 MySQL 支持的简单配置。

./configure --prefix=/usr \
   --sysconfdir=/etc/php \
   --with-config-file-path=/etc/php \
   --with-config-file-scan-dir=/etc/php/php.d \
   --bindir=/usr/bin \
   --docdir=/usr/share/doc \
   --sbindir=/usr/sbin \
   --libdir=/usr/lib64/php \
   --with-libdir=/usr/lib64/php \
   --libexecdir=/usr/libexec \
   --localstatedir=/var \
   --runstatedir=/run \
   --includedir=/usr/include \
   --localedir=/usr/local \
   --datarootdir=/usr/share \
   --datadir=/usr/share/php \
   --mandir=/usr/share/man \
   --infodir=/usr/share/info \
   --enable-fpm \
   --with-fpm-user=www-data \
   --with-fpm-group=www-data \
   --enable-mysqlnd \
   --enable-mysqlnd-compression-support \
   --enable-json \
   --with-openssl-dir \
   --with-jpeg-dir \
   --with-png-dir \
   --with-zlib-dir \
   --with-freetype-dir \
   --enable-gd-jis-conv \
   --enable-ftp \
   --enable-filter \
   --enable-fileinfo \
   --with-curl \
   --with-iconv \
   --with-bz2 \
   --with-zlib \
   --with-pcre-regex \
   --with-openssl \
   --enable-dom \
   --with-gettext \
   --with-mysqli=mysqlnd \
   --enable-pdo \
   --with-pdo-mysql=mysqlnd \
   --with-pdo-sqlite \
   --enable-simplexml \
   --enable-session \
   --enable-sysvsem \
   --enable-sysvmsg \
   --enable-sockets \
   --with-libxml-dir \
   --with-pear \
   --enable-opcache \
   --with-xmlrpc \
   --with-mhash \
   --with-sqlite3 \
   --enable-bcmath \
   --with-cdb \
   --enable-exif \
   --with-gd \
   --with-gmp \
   --enable-mbstring \
   --enable-mbregex \
   --enable-mbregex-backtrack \
   --with-onig \
   --with-readline \
   --enable-shmop \
   --enable-zip
make
sudo make install

4、创建配置文件,并将其复制到正确的位置。

cp php.ini-production /etc/php/php.ini
cp sapi/fpm/php-fpm.conf /etc/php/php-fpm.conf
cp sapi/fpm/www.conf /etc/php/php-fpm.d/www.conf
cp sapi/fpm/php-fpm.service /etc/systemd/system/php-fpm.service

5、需要着重提醒的是,如果文件不存在,则阻止 Nginx 将请求发送到后端的 PHP-FPM 模块, 以避免遭受恶意脚本注入的攻击。
将 php.ini 文件中的配置项 cgi.fix_pathinfo 设置为 0 。
打开 php.ini:

vim /etc/php/php.ini

定位到 cgi.fix_pathinfo= 并将其修改为如下所示:

cgi.fix_pathinfo=0

6、配置 php-fpm 服务

sudo systemctl start php-fpm

检查是否启动成功

sudo systemctl status php-fpm

如果出现错误:ERROR: [pool www] cannot get uid for user 'www-data'
则新建www-data 用户组:

groupadd www-data
useradd -g www-data -s /sbin/nologin -M www-data

设置服务自启动

sudo systemctl enable php-fpm

本文档未涵盖对 php-fpm 进行进一步配置的信息,如果您需要更多信息,请查阅相关文档。

OpenSSL

在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。

安装

1、准备编译环境

yum install gcc

2、下载OpenSSL源码

wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_1c.tar.gz

3、解压

tar -xzf OpenSSL_1_1_1c.tar.gz

4、配置

cd openssl-OpenSSL_1_1_1c
./config --prefix=/usr

5、编译&&安装

make && make install
ldconfig

7、查看安装版本

openssl version

OpenSSL 1.1.1c 28 May 2019

解决微软MVC请求响应的JSON的日期格式问题。需要结合StringBuilder

JavaScriptSerializer = {};
JavaScriptSerializer._charsToEscapeRegExs = [];
JavaScriptSerializer._charsToEscape = [];
JavaScriptSerializer._dateRegEx = new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"', 'g');
JavaScriptSerializer._escapeChars = {};
JavaScriptSerializer._escapeRegEx = new RegExp('["\\\\\\x00-\\x1F]', 'i');
JavaScriptSerializer._escapeRegExGlobal = new RegExp('["\\\\\\x00-\\x1F]', 'g');
JavaScriptSerializer._jsonRegEx = new RegExp('[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]', 'g');
JavaScriptSerializer._jsonStringRegEx = new RegExp('"(\\\\.|[^"\\\\])*"', 'g');
JavaScriptSerializer._init = function () {
    var replaceChars = ['\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', '\\u0005', '\\u0006', '\\u0007',
                        '\\b', '\\t', '\\n', '\\u000b', '\\f', '\\r', '\\u000e', '\\u000f', '\\u0010', '\\u0011',
                        '\\u0012', '\\u0013', '\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018', '\\u0019',
                        '\\u001a', '\\u001b', '\\u001c', '\\u001d', '\\u001e', '\\u001f'];
    JavaScriptSerializer._charsToEscape[0] = '\\';
    JavaScriptSerializer._charsToEscapeRegExs['\\'] = new RegExp('\\\\', 'g');
    JavaScriptSerializer._escapeChars['\\'] = '\\\\';
    JavaScriptSerializer._charsToEscape[1] = '"';
    JavaScriptSerializer._charsToEscapeRegExs['"'] = new RegExp('"', 'g');
    JavaScriptSerializer._escapeChars['"'] = '\\"';
    for (var i = 0; i < 32; i++) {
        var c = String.fromCharCode(i);
        JavaScriptSerializer._charsToEscape[i + 2] = c;
        JavaScriptSerializer._charsToEscapeRegExs[c] = new RegExp(c, 'g');
        JavaScriptSerializer._escapeChars[c] = replaceChars[i];
    }
}
JavaScriptSerializer.serialize = function (object) {
    var stringBuilder = new StringBuilder();
    var booleanWithBuilder = function (bool, builder) {
        if (typeof bool !== 'undefined') {
            builder.append(bool);
        } else {
            builder.append('false');
        }
    }
    var numberWithBuilder = function (number, builder) {
        if (typeof number !== 'undefined' && number.toString() !== 'NaN') {
            builder.append(number);
        } else {
            builder.append('null');
        }
    }
    var stringWithBuilder = function (string, builder) {
        builder.append('"');
        if (JavaScriptSerializer._escapeRegEx.test(string)) {
            if (JavaScriptSerializer._charsToEscape.length === 0) {
                JavaScriptSerializer._init();
            }
            if (string.length < 128) {
                string = string.replace(JavaScriptSerializer._escapeRegExGlobal,
                function (x) { return JavaScriptSerializer._escapeChars[x]; });
            }
            else {
                for (var i = 0; i < 34; i++) {
                    var c = JavaScriptSerializer._charsToEscape[i];
                    if (string.indexOf(c) !== -1) {
                        if ($.browser.opera || $.browser.mozilla) {
                            string = string.split(c).join(JavaScriptSerializer._escapeChars[c]);
                        }
                        else {
                            string = string.replace(JavaScriptSerializer._charsToEscapeRegExs[c],
                            JavaScriptSerializer._escapeChars[c]);
                        }
                    }
                }
            }
        }
        builder.append(string);
        builder.append('"');
    }
    var dateWithBuilder = function (date, builder) {
        if (date && date.toString() !== 'NaN') {
            builder.append('"\\/Date(');
            var timeOffset = date.getTimezoneOffset() * 60 * 1000;
            if (timeOffset != 0) {
                var time = date.getTime() - timeOffset;
                builder.append(time);
            }
            else {
                builder.append(date.getTime());
            }
            builder.append(')\\/"');
        } else {
            builder.append('null');
        }
    }
    var plainObjectWithBuilder = function (plainObject, builder) {
        builder.append('{');
        var row = 0;
        for (var item in plainObject) {
            if (row++ > 0) {
                builder.append(',');
            }
            stringWithBuilder(item, builder);
            builder.append(':');
            withBuilder(plainObject[item], builder);
        }
        builder.append('}');
    }
    var arrayWithBuilder = function (array, builder) {
        if (array) {
            builder.append('[');
            if (array.length > 0) {
                $.each(array, function (i, item) {
                    if (i > 0) {
                        builder.append(',');
                    }
                    withBuilder(item, builder);
                });
            }
            builder.append(']');
        } else {
            builder.append('null');
        }
    }
    var withBuilder = function (object, builder) {
        builder = builder || new StringBuilder();
        var type = $.type(object);
        switch (type) {
            case 'object':
                if (object) {
                    if (jQuery.isPlainObject(object)) {
                        plainObjectWithBuilder(object, builder);
                    } else {
                        builder.append('null');
                    }
                } else {
                    builder.append('null');
                }
                break;
            case 'array':
                arrayWithBuilder(object, builder);
                break;
            case 'number':
                numberWithBuilder(object, builder);
                break;
            case 'string':
                stringWithBuilder(object, builder);
                break;
            case 'date':
                dateWithBuilder(object, builder);
                break;
            case 'boolean':
                booleanWithBuilder(object, builder);
                break;
            default:
                builder.append('null');
                break;
        }
    }

    withBuilder(object, stringBuilder);

    return stringBuilder.toString();
}
JavaScriptSerializer.deserialize = function (data, secure) {
    if (data == null || typeof data !== "string" || data.length === 0) {
        return null;
    }
    var exp = data.replace(JavaScriptSerializer._dateRegEx, "$1new Date($2)");
    try {
        if (secure && JavaScriptSerializer._jsonRegEx.test(exp.replace(JavaScriptSerializer._jsonStringRegEx, ''))) {
            throw null;
        }
    } catch (e) {
        throw 'Cannot deserialize. The data does not correspond to valid JSON.';
    }
    return eval('(' + exp + ')');
}

StringBuilder = function (initialText) {
    this._array = (typeof (initialText) !== 'undefined' && initialText !== null && initialText !== '') ? [initialText] : [];
    this.append = function (text) {
        this._array[this._array.length] = text;
    }
    this.appendLine = function (text) {
        this._array[this._array.length] = ((typeof (text) === 'undefined') || (text === null) || (text === '')) ? '\r\n' : text + '\r\n';
    }
    this.clear = function (text) {
        this._array = [];
    }
    this.isEmpty = function () {
        return (this._array.length == 0 ? true : false);
    }
    this.toString = function (separator) {
        separator = separator || ''
        var array = this._array;
        if (separator !== '') {
            for (var i = 0; i < array.length; ) {
                if ((typeof (array[i]) === 'undefined') || (array[i] === '') || (array[i] === null)) {
                    array.splice(i, 1);
                }
                else {
                    i++;
                }
            }
        }
        return array.join(separator);
    }
    this.indexOf = function (searchvalue) {
        return this._array.indexOf(searchvalue);
    }
    this.contains = function (text) {
        return this._array.contains(text);
    }
}

public sealed class AcrobatUtil
{
	public string ConvertToExecl(string inputFileName, string outputFileName)
	{
		//判断文件是否存在
		if (!File.Exists(inputFileName))
		{
			return "File Is Missing";
		}
		try
		{
			//判断是否已经安装Acrobat
			string acrobatPath = GetAppPath();
			if (acrobatPath == null)
			{
				return "Adobe Acrobat not installed.";
			}

			var aVDoc = new AcroAVDoc();
			aVDoc.Open(inputFileName, "");
			CAcroPDDoc PDDoc = (CAcroPDDoc)aVDoc.GetPDDoc();
			object jsObj = PDDoc.GetJSObject();
			var jsObjType = jsObj.GetType();
			//另存为
			jsObjType.InvokeMember(
							"saveAs",
							BindingFlags.InvokeMethod |
							BindingFlags.Public |
							BindingFlags.Instance,
							null, jsObj, new object[] { outputFileName, "com.adobe.acrobat.xlsx" });
/*
另存为更多格式
html htm      com.adobe.acrobat.html
jpeg jpg      com.adobe.acrobat.jpeg
docx          com.adobe.acrobat.docx
doc           com.adobe.acrobat.doc
png           com.adobe.acrobat.png
ps            com.adobe.acrobat.ps
rft           com.adobe.acrobat.rft
xlsx          com.adobe.acrobat.xlsx
xls           com.adobe.acrobat.spreadsheet
txt           com.adobe.acrobat.accesstext
tiff tif      com.adobe.acrobat.tiff
xml           com.adobe.acrobat.xml-1-00
*/
			//关闭文档
			aVDoc.Close(1);
		}
		catch (Exception ex)
		{
			return "Error:" + ex.Message;
		}
		return null;
	}
	
	//获取Acrobat安装路径
	private string GetAppPath()
	{
		string acrobatPath = null;
		using (RegistryKey acrobatRegistryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Adobe\Adobe Acrobat"))
		{
			if (acrobatRegistryKey == null)
			{
				return acrobatPath;
			}
			string acrobatVersion = acrobatRegistryKey.GetValue("TrackName").ToString();
			using (RegistryKey acrobatInstallPathRegistryKey = acrobatRegistryKey.OpenSubKey(acrobatVersion + @"\InstallPath"))
			{
				if (acrobatInstallPathRegistryKey == null)
				{
					return acrobatPath;
				}
				acrobatPath = acrobatInstallPathRegistryKey.GetValue("").ToString() + @"\Acrobat.exe";
			}
		}
		return acrobatPath;
	}
}