Boost开发指南-1.3date_time

news2024/11/18 20:40:57

date_time

date_time库勇敢地面对了这个挑战,并成功地解决了大部分问题。它是一个非常全面且灵活的日期时间库,基于我们日常使用的公历(即格里高利历),可以提供时间相关的各种所需功能,如精确定义的时间点、时间段和时间长度、加减若干天/月/年、日期迭代器等等。date_time库还支持无限时间和无效时间这种实际生活中有用的概念,而且可以与c的传统时间结构tm相互转换,提供向下支持。

编译与使用

date_time库需要编译才能使用,在jamfile里指定lib的语句是:

lib boost_data_time;

date_time 库包含两个部分,分别是处理日期的 gregorian和处理时间的posix_time,需要包含如下的头文件:

//处理日期的组件
#inlcude <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;

//处理时间的组件
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;

基本概念

时间的处理很复杂,因此在使用date_time库之前,我们需要明确一些基本概念。

如果把时间想象成一个向前和向后都无限延伸的实数轴,那么时间点就是数轴上的一个点,时间段就是两个时间点之间确定的一个区间,时长(时间长度)则是一个有正负号的标量,它是两个时间点之差,不属于数轴。

时间点、时间段和时长三者之间可以进行运算,例如时间点+时长=时间点,时长+时长=时长,时间段∩时间段=时间段、时间点∈时间段等等,但有的运算也是无意义的,如时间点+时间点、时长+时间段等等。这些运算都基于生活常识,很容易理解,但在编写时间处理程序时必须注意。

date_time库支持无限时间和无效时间(NADT,Not Available Date Time)这样特殊的时间概念,类似于数学中极限的含义。时间点和时长都有无限的值,它们的运算规则比较特别,例如+ oo时间点+时长=+∞时间点,时间点+∞时长=+∞时间点。如果正无限值与负无限值一起运算将有可能是无效时间,如+∞时长-时长=NADT。

date_time库中用枚举special_values定义了这些特殊的时间概念,它位于名字空间boost::date_time,并被using语句引入其他子名字空间。

pos_infin                   表示正无限
neg_infin                   表示负无限
not_a_date_time             无效时间
min_date_time               可表示的最小日期或时间
max_date_time               可表示的最大日期或时间

处理日期

我们首先研究date_time库的日期处理部分,因为日期只涉及年月日,较时间少处理时分秒三个量,相当于数轴上的整数,要容易学习一些。

date_time库的日期基于格里高利历,支持从1400-01-01到9999-12-31之间的日期计算(很遗憾,它不能处理公元前的日期,不能用它来研究古老的历史)。它位于名字空间boost:: gregorian,为了使用date_time库的日期功能,需要包含头文件<boost/date_time/gregorian/gregorian.hpp>,即:

#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;

日期

date是 date_time 库处理日期的核心类,使用一个32位的整数作为内部存储,以天为单位表示时间点概念。它的类摘要如下:

template<typename T, typename calendar, typename duration_type_>
class date {
public:
   date(year_type, month_type, day_type); //构造函数
   date(const ymd_type &);
   
   year_type          year() const; //基本操作函数
   month_type         month() const;
   day_type           day() const;
   day_of_week_type   day_of_week() const;
   ymd_type           year_month_day() const;
   
   bool operator<(const date_type &) const; //比较操作函数
   bool operator==(const date_type &) const;
   
   bool is_special() const; //有效性验证
   bool is_not_a_date() const;
   bool is_infinity() const;
   bool is_pos_infinity() const;
   bool is_neg_infinity() const;
   special_values as_special() const;
   duration_type operator-(const date_type &) const;
   ...   //其他日期运算
};

date是一个轻量级的对象,很小,处理效率很高,可以被拷贝传值。date也全面支持比较操作和流输入输出,因此我们完全可以把它当成一个像int、string那样的基本类型来使用。

创建日期对象

有很多种方式可以创建一个日期对象。

空的构造函数会创建一个值为not_a_date_time的无效日期;顺序传入年月日值则创建一个对应日期的date对象,例如:

date d1; //一个无效的日期
date d2(2010, 1, 1); //使用数字构造日期
date d3(2000, Jan, 1); //也可以使用英文指定月份
date d4(d2); //date支持拷贝构造

assert(d1 == date(not_a_date_time)); //比较一个临时对象
assert(d2 == d4); //date支持比较操作
assert(d3 < d4);

date 也可以从一个字符串产生,这需要使用工厂函数from_string()或fromundelimited_string()。前者使用分隔符(斜杠或者连字符)分隔年月日格式的字符串,后者则是无分隔符的纯字符串格式。例如:

date d1 = from_string("1999-12-31");
date d2 (from_string("2015/1/1"));
date d3 = from_undelimited_string("20011118");

day_clock 是一个天级别的时钟,它也是一个工厂类,调用它的静态成员函数local_day()universal_day()会返回一个当天的日期对象,分别是本地日期和UTC日期。day_clock 内部使用了c标准库的 localtime()gmtime()函数,因此local_day()的行为依赖于操作系统的时区设置。例如:

cout << day_clock::local_day() << endl;
cout << day_clock::universal_day() << endl;

我们也可以使用特殊时间概念枚举 special_values 创建一些特殊的日期,在处理如无限期的某些情形下会很有用:

date d1(neg_infin); //负无限日期
date d2(pos_infin); //正无限日期
date d3(not_a_date_time): //无效日期
date d4(max_date_time); //最大可能日期9999-12-31
date d5(min_date_time);  //最小可能日期1400-01-01

使用cout将它们输出,显示将会是:

-infinity
+infinity
not-a-date-time
9999-Dec-31
1400-Jan-01

如果创建日期对象时使用了非法的值,例如日期超过了1400-01-01到9999-12-31的范围,或者使用不存在的月份或日期,那么date_time库会抛出异常(而不是转换为一个无效日期),可以使用what ()获得具体的错误信息。

下面的date对象构造均会抛出异常:

date d1(1399, 12, 1); //超过日期下限
date d2(10000, 1, 1); //超过日期上限
date d3(2010, 2, 29); //不存在的日期

访问日期

date类的对外接口很像c语言中的tm结构,也可以获取它保存的年、月、日、星期等成分,但 date提供了更多的操作。

成员函数year() 、 month()和 day()分别返回日期的年、月、日:

date d(2014, 4, 1);
assert(d.year() == 2014);
assert(d.month() == 4);
assert(d.day() == 1);

成员函数year_month_day()返回一个date::ymd_type结构,可以一次性地获取年月日数据:

date::ymd_type ymd = d.year_month_day();
assert(ymd.year == 2014);
assert(ymd.month == 4);
assert(ymd.day == 1);

成员函数 day_of_week ()返回date 的星期数,0表示星期天。day_of_year()返回date是当年的第几天(最多是366)。end_of_month()返回当月的最后一天的date对象:

cout << d.day_of_week() << endl; //输出Tue
cout << d.day_of_year() << endl; //输出91
assert(d.end_of_month() == date(2014, 4, 30));

成员函数week_number()返回date所在的周是当年的第几周,范围是0至53:

cout << date(2014, 1, 10).week_number() << endl; //输出2
cout << date(2014, 1, 1).week_number() << endl; //输出1
cout << date(2015, 1, 1).week_number() << endl; //输出1

date还有五个is_xxx()函数,用于检验日期是否是一个特殊日期,它们是:

is_infinity()       是否是一个无限日期
is_neg_infinity()   是否是一个负无限日期
is_pos_infinity()   是否是一个正无限日期
is_not_a_date()     是否是一个无效日期
is_special()        是否是任意一个特殊日期

他们用法如下:

assert(date(pos_infin).is_infinity());
assert(date(pos_infin).is_pos_infinity());
assert(date(neg_infin).is_neg_infinity());
assert(date(not_a_date_time).is_not_a_date());
assert(date(not_a_date_time).is_special());
assert(!date(2014,11,1).is_special());

日期的输出

date对象可以很方便地转换成字符串,它提供了三个自由函数。

to_simple_string(date d):           转换为YYYY-mmm-DD格式的字符串,其中的mmm为3字符的英文月份名
to_iso_string(date d):              转换为YYYYMMDD格式的数字字符串
to_iso_extended_string(date d):     转换为YYYY-MM-DD格式的数字字符串

date也支持流输入输出,默认使用YYYY-mmm-DD格式。例如:

date d(2008, 11, 20);
cout << to_simple_string(d) << endl;
cout << to_iso_string(d) << endl;
cout << to_iso_extended_string(d) << endl;
cout << d << endl;

cin >> d;
cout << d;

程序的运行结果如下:

2008-Nov-20
20081120
2008-11-20
2008-Nov-20
2010-Jan-02(用户的输入)
2010-Jan-02

转换tm结构

date支持与c标准库中的tm结构相互转换,转换的规则和函数如下:

to_tm(date)  date转换到tm。tm的时分秒成员(tm_hour, tm_min, tm_sec)均置为0,夏令时标志tm_isdst置为-1(表示未知)
date_from_tm(tm datetm) tm转换到date。只使用年、月、日三个成员(tm_year, tm_mon, tm_mday), 其他成员均被忽略。

下面的代码示范了date 与tm的相互转换:

date d(2014, 2, 1);
tm t = to_tm(d);
assert(t.tm_hour == 0 && t.tm_min == 0);
assert(t.tm_year == 114 && t.tm_mday == 1);

date d2 = date_from_tm(t);
assert(d == d2);

日期长度

日期长度是以天为单位的时长,是度量时间长度的一个标量。它与日期不同,值可以是任意的整数,可正可负。基本的日期长度类是date_duration,它的类摘要如下:

class date_duration
{
public:
   date_duration(long); //构造函数
   date_duration(special_values); 
   long days() const; //成员访问函数
   bool is_special() const;
   bool is_negative() const;
   bool operator==(const date_duration &) const;
   ... //其他操作符定义
   static date_duration unit(); //时长单位
};

date_duration可以使用构造函数创建一个日期长度,成员函数days()返回时长的天数,如果传入特殊时间枚举值则构造出一个特殊时长对象。is_special()is_negative()可以判断date_duration对象是否为特殊值、是否是负值。unit()返回时长的最小单位,即date_duration(1)

date_duration支持全序比较操作(==、!=、<、<=等),也支持完全的加减法和递增递减操作,用起来很像一个整数。此外 date_duration还支持除法运算,可以除以一个整数,但不能除以另一个date_duration,其他的数学运算如乘法、取模、取余则不支持。

date_time库为date_duration定义了一个常用的typedef: days,这个新名字更好地说明了date_duration的含义——它是一个天数的计量。

示范days (date_duration)用法的代码如下:

days dd1(10), dd2(-100), dd3(255);

assert(dd1 > dd2 && dd1 < dd3);
assert(dd1 + dd2 == days(-90));
assert((dd1 + dd3).days() == 265);
assert(dd3 / 5 == days(51));

为了方便计算时间长度,date_time库还提供了months、years、weeks等另外三个时长类,分别用来表示月、年和星期,它们的含义与days类似,但行为不太相同。

months和 years 全面支持加减乘除运算,使用成员函数number_of_months()number_of_years()可获得表示的月数和年数。weeks是date_duration的子类,除了构造函数以7为单位外其他的行为与days完全相同,可以说是一个days的近义词。

示范这三个时长类基本用法的代码如下:

weeks w(3); //3个星期
assert(w.days() == 21);
months m(5); //5个月
years y(2); //2年
months m2 = y + m;
assert(m2.number_of_months() == 29); //2年零5个月
assert((y * 2).number_of_years() == 4);

日期运算

date支持加减运算,两个date对象的加操作是无意义的(date_time库会以编译错误的方式通知我们),date主要是与时长概念配合运算。

例如,下面的代码计算了从2000年1月1日到2014年11月18日的天数,并执行其他的日期运算:

#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;

int main()
{
	date d1(2000, 1, 1), d2(2017, 11, 18);
	cout << d2 - d1 << endl; //5435天
	assert(d1 + (d2 - d1) == d2);

	d1 += days(10); //2000-1-11
	assert(d1.day() == 11);
	d1 += months(2); //2000-3-11
	assert(d1.month() == 3 && d1.day() == 11);
	d1 -= weeks(1); //2000-3-04
	assert(d1.day() == 4);

	d2 -= years(10); //2000-11-18
	assert(d2.year() == d1.year() + 7);

	{
		date d1(2017, 1, 1);

		date d2 = d1 + days(pos_infin);
		assert(d2.is_pos_infinity());

		d2 = d1 + days(not_a_date_time);
		assert(d2.is_not_a_date());
		d2 = date(neg_infin);
		days dd = d1 - d2;
		assert(dd.is_special() && !dd.is_negative());
	}

	{
		date d(2017, 3, 30);
		d -= months(1);
		d -= months(1);
		d += months(2);
		assert(d.day() == 31);
	}
}

日期与特殊日期长度、特殊日期与日期长度进行运算的结果也会是特殊日期:

date d1(2017, 1, 1);

date d2 = d1 + days(pos_infin);
assert(d2.is_pos_infinity());

d2 = d1 + days(not_a_date_time);
assert(d2.is_not_a_date());
d2 = date(neg_infin);
days dd = d1 - d2;
assert(dd.is_special() && !dd.is_negative());

在与months、years这两个时长类进行计算时要注意:如果日期是月末的最后一天,那么加减月或年会得到同样的月末时间,而不是简单的月份或者年份加1,这是合乎生活常识的。但当天数是月末的28、29时,如果加减月份到2月份,那么随后的运算就总是月末操作,原来的天数信息就会丢失。例如:

date d(2014, 3, 30);
d -= months(1); //2014-2-28,变为月末,原30的日期信息丢失
d -= months(1); //2014-1-31
d += months(2); //2014-3-31
assert(d.day() == 31); //与原来日期不相等

使用days则不会出现这样的问题,如果担心weeks、months、years这些时长类被无意使用进而扰乱了代码,可以undef宏BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES,这将使 date_time库不包含它们的定义头文件<boost/date_time/gregorian/greg_duration_types.hpp>

日期区间

date_time库使用date_period类来表示日期区间的概念,它是时间轴上的一个左闭右开区间,端点是两个date对象。区间的左边界必须小于右边界,否则date_period将表示一个无效的日期区间。

date_period的类摘要如下:

class date_period
{
public:
   period(date, date);
   period(date, days);

   date begin() const;
   date end() const;
   date last() const;
   days length() const;
   bool is_null() const;

   bool operator==(const period &) const;
   bool operator<(const period &) const;
  
   void shift(const days &);
   void expend(const days &);

   bool contains(const date &) const;
   bool contains(const period &) const;
   bool intersects(const period &) const;
   bool is_adjacent(const period &) const;
   bool is_before(const date &) const;
   bool is_after(const date &) const;
   period intersection(const period &) const;
   period merge(const period &) const;
   period span(const period &) const;
};

date_period可以指定区间的两个端点构造,也可以指定左端点再加上时长构造,通常后一种方法比较常用,相当于生活中从某天开始的一个周期。例如:

date_period dp1(date(2014,1,1), days(20));
date_period dp2(date(2014,1,1), date(2013,1,1)); //无效
date_period dp3(date(2014,3,1), days(-20)); //无效

成员函数begin()和 last()返回日期区间的两个端点,而end()返回 last()后的第一天,与标准容器中的end()含义相同,是一个“逾尾的位置”。length()返回日期区间的长度,以天为单位。如果日期区间在构造时使用了左大右小的端点或者日期长度是0,那么is_nul1()函数将返回true。例如:

date_period dp(date(2014,1,1), days(20));

assert(!dp.is_null());
assert(dp.begin().day() == 1);
assert(dp.last().day() == 20);
assert(dp.end().day() == 21);
assert(dp.length().days() == 20);

date_period可以进行全序比较运算,但比较不是依据日期区间的长度,而是依据区间的端点,即第一个区间的end()和第二个区间的begin(),判断两个区间在时间轴上的位置大小。如果两个日期区间相交或者包含,那么比较操作无意义。

date_period也支持输入输出操作符,默认的输入输出格式是一个[YYYY-mmm-DD/YYYY-mmm-DD]形式的字符串。例如:

date_period dp1(date(2014,1,1), days(20));
date_period dp2(date(2014,2,19), days(10));
cout << dp1; //[2014-Jan-01/2014-Jan-20]
assert(dp1 < dp2);

代码实例

#include <iostream>
using namespace std;

//#define DATE_TIME_NO_DEFAULT_CONSTRUCTOR
#include <boost/date_time/gregorian/gregorian.hpp>
using namespace boost::gregorian;

//

void case1()
{
	date d1;
	date d2(2010, 1, 1);
	date d3(2000, Jan, 1);
	date d4(d2);

	assert(d1 == date(not_a_date_time));
	assert(d2 == d4);
	assert(d3 < d4);
}

//

void case2()
{
	date d1 = from_string("1999-12-31");
	date d2(from_string("2015/1/1"));
	date d3 = from_undelimited_string("20011118");

	cout << d1 << d2 << d3 << endl;

	cout << day_clock::local_day() << endl;
	cout << day_clock::universal_day() << endl;

}

//
void case3()
{
	date d1(neg_infin);
	date d2(pos_infin);
	date d3(not_a_date_time);
	date d4(max_date_time);
	date d5(min_date_time);

	cout << d1 << d2 << d3 << d4 << d5 << endl;

	try
	{
		//date d1(1399,12,1);
		//date d2(10000,1,1);
		date d3(2017, 2, 29);
	}
	catch (std::exception& e)
	{
		cout << e.what() << endl;
	}
}

//
void case4()
{
	date d(2017, 6, 1);
	assert(d.year() == 2017);
	assert(d.month() == 6);
	assert(d.day() == 1);

	date::ymd_type ymd = d.year_month_day();
	assert(ymd.year == 2017);
	assert(ymd.month == 6);
	assert(ymd.day == 1);

	cout << d.day_of_week() << endl;
	cout << d.day_of_year() << endl;
	assert(d.end_of_month() == date(2017, 6, 30));

	cout << date(2015, 1, 10).week_number() << endl;
	cout << date(2016, 1, 10).week_number() << endl;
	cout << date(2017, 1, 10).week_number() << endl;

	assert(date(pos_infin).is_infinity());
	assert(date(pos_infin).is_pos_infinity());
	assert(date(neg_infin).is_neg_infinity());
	assert(date(not_a_date_time).is_not_a_date());
	assert(date(not_a_date_time).is_special());
	assert(!date(2017, 5, 31).is_special());


}

//
void case5()
{
	date d(2017, 1, 23);

	cout << to_simple_string(d) << endl;
	cout << to_iso_string(d) << endl;
	cout << to_iso_extended_string(d) << endl;
	cout << d << endl;

	//cout << "input date:";
	//cin >>d;
	//cout << d;

}

//
void case6()
{
	date d(2017, 5, 20);
	tm t = to_tm(d);
	assert(t.tm_hour == 0 && t.tm_min == 0);
	assert(t.tm_year == 117 && t.tm_mday == 20);

	date d2 = date_from_tm(t);
	assert(d == d2);

}

//
void case7()
{
	days dd1(10), dd2(-100), dd3(255);

	assert(dd1 > dd2 && dd1 < dd3);
	assert(dd1 + dd2 == days(-90));
	assert((dd1 + dd3).days() == 265);
	assert(dd3 / 5 == days(51));

	weeks w(3);
	assert(w.days() == 21);

	months m(5);
	years y(2);

	months m2 = y + m;
	assert(m2.number_of_months() == 29);
	assert((y * 2).number_of_years() == 4);

}

//
void case8()
{
	date d1(2000, 1, 1), d2(2017, 11, 18);
	cout << d2 - d1 << endl;
	assert(d1 + (d2 - d1) == d2);

	d1 += days(10);
	assert(d1.day() == 11);
	d1 += months(2);
	assert(d1.month() == 3 && d1.day() == 11);
	d1 -= weeks(1);
	assert(d1.day() == 4);

	d2 -= years(10);
	assert(d2.year() == d1.year() + 7);

	{
		date d1(2017, 1, 1);

		date d2 = d1 + days(pos_infin);
		assert(d2.is_pos_infinity());

		d2 = d1 + days(not_a_date_time);
		assert(d2.is_not_a_date());
		d2 = date(neg_infin);
		days dd = d1 - d2;
		assert(dd.is_special() && !dd.is_negative());
	}

	{
		date d(2017, 3, 30);
		d -= months(1);
		d -= months(1);
		d += months(2);
		assert(d.day() == 31);
	}
}

//
void case9()
{
	date_period dp1(date(2017, 1, 1), days(20));
	date_period dp2(date(2017, 1, 1), date(2016, 1, 1));
	date_period dp3(date(2017, 3, 1), days(-20));

	date_period dp(date(2017, 1, 1), days(20));

	assert(!dp.is_null());
	assert(dp.begin().day() == 1);
	assert(dp.last().day() == 20);
	assert(dp.end().day() == 21);
	assert(dp.length().days() == 20);

	{
		date_period dp1(date(2017, 1, 1), days(20));
		date_period dp2(date(2017, 2, 19), days(10));

		cout << dp1;                        //[2010-Jan-01/2010-Jan-20]
		assert(dp1 < dp2);
	}
}

//

int main()
{
	case1();
	case2();
	case3();
	case4();
	case5();
	case6();
	case7();
	case8();
	case9();
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS入门学习笔记+案例【一】

目录 一、CSS 是什么 二、引入方式 2.2 行内样式表 2.3 外部样式 三、 代码风格 3.1 样式格式 3.2 样式大小写 3.3 空格规范 四、 选择器 4.1 选择器的功能 4.2 选择器的种类 复合选择器小结 看完这篇博客 你将 掌握 CSS 基本语法规范和代码书写风格 掌握 CSS 选择…

ARM微架构

目录 1.流水线 2.指令流水线 3. 多核处理器​编辑 4. 工程搭建 4.1为Keil软件配置编译工具链 5.程序编写 5.1 数据处理指令 5.2 带标志位的加法ADC ADDS 5.3 跳转指令B\BL 5.4 单寄存器内存访问 5.5 批量寄存器内存访问 5.6 满减操作 1.流水线 2.指令流水线 3.…

Ansible从入门到精通【三】

大家好&#xff0c;我是早九晚十二&#xff0c;目前是做运维相关的工作。写博客是为了积累&#xff0c;希望大家一起进步&#xff01; 我的主页&#xff1a;早九晚十二 专栏名称&#xff1a;Ansible从入门到精通 立志成为ansible大佬 ♣ansible的高级指令 ansible-playbook写一…

Java 集合中 ArrayList 的扩容机制原理(面试+读源码)

在 Java 中&#xff0c;ArrayList 内部是通过一个数组来存储元素的&#xff0c;是一个数组结构的存储容器。当向一个 ArrayList 中添加元素时&#xff0c;如果当前数组已经满了&#xff0c;就需要扩容。 集合的继承关系图 一、面试回答 ( ArrayList 的扩容机制原理 ) 面试…

Vue 脚手架(打包工具)的理解 - 配置文件理解

序言 Vue 脚手架是 Vue 作为一个前端开发项目的最核心点&#xff0c;将JavaScript、CSS、HTML这几种前端自动整合&#xff0c;极大的简化了前端开发工作。 没有 Vue 脚手架&#xff0c;就没有 Vue &#xff0c;这是一定的&#xff0c;Java 语言和C语言都需要编译&#xff0c;…

【论文阅读】Analyzing group-level emotion with global alignment kernel based approach

【论文阅读】Analyzing group-level emotion with global alignment kernel based approach 摘要1.介绍与相关工作2.方法3.实验 摘要 本篇博客参考IEEE于2022年收录的论文Analyzing group-level emotion with global alignment kernel based approach&#xff0c;对其主要内容…

new一个ObjectInputStream为什么会出现java.io.EOFException

一、举例代码 package com.softeem.wolf.homework06;import java.io.*;/*** Created by 苍狼* Time on 2023-05-24*/ public class App {public static void main(String[] args) throws IOException {ObjectInputStream ois null;ObjectOutputStream oos null;ois new Obj…

功率信号源的特点和用途是什么

功率信号源是一种电子测量仪器&#xff0c;它集信号发生器与功率放大器为一体&#xff0c;具有高电压、大功率的特点。在电子实验室中&#xff0c;功率信号源可以帮助用户驱动压电陶瓷、换能器以及电磁线圈等&#xff0c;有效地解决了驱动负载和放大功率的问题。下面我们来具体…

Linux:LAMP的架构与环境配置

这里写目录标题 一、LAMP1.1 LAMP是什么1.2 安装顺序 二、编译安装Apache httpd服务2.1 关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt目录下2.2 安装环境依赖包2.3 配置软件模块2.4 编译及安装2.5 优化配置文件路径2.6 添加httpd系统服务2.7 修改httpd 服务配置文件2…

MySql基础学习(2)

MySql基础学习 一、函数1.1 字符串函数1.2 数值函数1.3 日期函数1.4 流程控制语句 二、约束2.1 约束基本分类2.2 外键约束2.3 删除/更新行为 三、多表查询3.1 多表关系3.2 多表查询概述3.3 多表查询分类3.3.1 内连接3.3.2 外连接3.3.3 连接查询-自连接 3.4 联合查询-union&…

[SpringBoot]xml写mapper

创建工程[SpringBoot框架]如何使用SpringBoot框架_万物更新_的博客-CSDN博客 实现步骤: 测试: <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd…

Visual Studio || Visual Studio Code 连接 SQL Server 和 mysql

使用Visua Studio链接本地SQL Server和服务器上的mysql。 软件版本&#xff1a; Visual Studio 2022&#xff1b;Visual Studio Code 2023&#xff1b;SQL Server 2019mysql8.0 一、软件准备二、连接SQL Server2.1 使用Visual Studio 连接SQL Server2.2 使用VS Code连接SQL Ser…

【qemu】将vmdk转换为img镜像教程

qemu软件下载地址&#xff1a; 64位下载地址&#xff1a;QEMU for Windows – Installers (64 bit) 32位下载地址&#xff1a;QEMU for Windows – Installers (32 bit) 找到qemu的目录&#xff0c;然后使用cmd打开&#xff08;qemu软件没有封装exe包&#xff0c;所以只能用…

伺服系统使用S曲线

在之前文章《S形曲线规划方式汇总》 介绍过贝塞尔曲线方式&#xff0c;并且在Marlin开源工程中也有贝塞尔曲线步进系统的实现方式。本篇介绍伺服系统中基于时间分割法实现的贝塞尔S曲线。 1 贝塞尔曲线路程规划 上文中推导过贝塞尔曲线&#xff0c;本文直接用结论&#xff1a…

分享一下如何使用echarts绘制散点图

文章目录 散点图源码地址 散点图 今天我来分享一下如何使用echarts绘制散点图 首先&#xff0c;我们需要引入echarts库。可以通过以下代码在HTML文件中引入&#xff1a; <script src"https://cdn.jsdelivr.net/npm/echarts5.2.0/dist/echarts.min.js"></s…

整合SSM(Spring + SpringMVC + Mybatis)

7、整合SSM 7.1、环境要求7.2、数据库环境7.3、基本环境搭建7.4、Mybatis层编写7.5、Spring层7.6、SpringMVC层7.7、小结及展望 7.1、环境要求 环境&#xff1a; IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 要求&#xff1a; 需要熟练掌握MySQL数据库&#xff0c;Spring&#…

FMT ICF5实时仿真,不止于飞控

基于ICF5的实时仿真 作为FMT的首款自研的国产开源飞控硬件平台&#xff0c;ICF5不仅功能强大&#xff0c;而且高颜值和高性价比获得了用户的一致好评。 FMT ICF5飞控 ICF5购买链接​item.taobao.com/item.htm?id705459383848&ali_refida3_430620_1006:1123834906:N:O3mc…

常见的主流自动化测试框架,这5种真的帮助巨大

今天我们要向大家介绍的是常见5种主流自动化测试框架&#xff0c;包括优缺点等内容&#xff0c;供大家参考学习。 1.ATF 自动化测试框架AutoTestFramework是B/S架构框架&#xff0c;可实现Selenium等多种自动化测试全流程、团队化管理的高级框架平台&#xff0c;通过集成自动化…

Zookeeper+消息队列Kafka

一、Zookeeper 概述 官方下载地址&#xff1a;Index of /dist/zookeeper 1.1 Zookeeper 定义 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 1.2 Zookeeper 工作机制 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设…

PyCharm配置Opencv(多人亲测可用)

23/5/29更新&#xff1a; 之前由于只安装opencv-python-contrib这个包&#xff0c;导致Opencv版本过高&#xff0c;有些算法无法使用&#xff0c; 所以这里更新安装opencv-contrib-python这个包&#xff0c;具体如下配置。 ————————————————————————…