灵感
给工人发工资是按小时计算的,每次都要上网,我比较喜欢用 Hours Calculator ,也喜欢它的其它的功能, 做个类似的。
我以为是 Python,结果在学 javascript 看 HTML,页面的基础还停留在 Frontpage 2000 因为 MS-Office 2000 里有的。
忽略我的美学... 已排版尽力
这是一个长期的项目当遇到生活计算时,就会添加进来,也许会吧
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.****.net/davenian/article/details/143054998 <- 开篇文章
年龄计算器 Age Calculator
根据输入的出生日期和指定日期,精确计算出年龄并以不同时间单位(年、月、周、天、小时、分钟、秒)展示。不仅计算从出生日期到当前日期的年龄,还可以输入指定日期来计算在那一天的年龄。
此外,程序还会显示距离下一个生日的天数,并标明具体日期和星期。
目录结构
Calculator
│
├── app.py Flask 主程序
├── Dockerfile Docker 容器的配置文件
├── requirements.txt 应用依赖的 Python 包
├── static javascript files of pages
│ ├── agecal
│ │ └── agecal.js
│ ├── time
│ │ └── timercal.js
│ ├── workhours
│ │ └── workhourscal.js
│ └── styles.css 样式表
└── templates
├── converters
│ ├── agecal.html 年龄计算器页面
│ ├── time.html 时间转换器页面
│ └── workhours.html 工作时常计算器页面
└── index.html 主页模板
服务端
添加 agecal 路由
app.py 当前代码
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/converters/time')
def time_converter():
# 渲染位于 templates/converters/time.html 的模板
return render_template('converters/time.html')
@app.route('/converters/agecal')
def age_calculator():
# 渲染位于 templates/converters/age calculator 的模板
return render_template('converters/agecal.html')
@app.route('/converters/workhours')
def work_hours():
return render_template('converters/workhours.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9007, debug=True)
说明
见这里:<Project-11 Calculator> 计算器 0.1时间换算器 Time Conversion Calculator-****博客
index.html 当前代码
<!DOCTYPE html>
<!-- index.html-->
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>主页 - 单位换算工具</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="body">
<div class="centered">
<h1>单位换算工具</h1>
<p>请选择一个单位换算工具:</p>
</div>
<div class="content centered" >
<ul class="tools-list">
<li><a href="{{ url_for('time_converter') }}">时间换算器</a></li>
<li><a href="{{ url_for('work_hours') }}">工作小时计算器</a></li>
<li><a href="{{ url_for('age_calculator') }}">年龄计算器</a></li>
<!-- 您可以在这里添加更多链接到其他转换工具 -->
</ul>
</div>
</div>
</body>
</html>
说明
在 css file 更新比较多, 定义按钮宽度 180px 居中文字等
功能见:<Project-11 Calculator> 计算器 0.1时间换算器 Time Conversion Calculator-****博客
agecal.html 当前代码
<!DOCTYPE html>
<!--agecal.html-->
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>年龄计算器</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
<!-- 使用 Flask 的 url_for 函数来引用静态文件 -->
</head>
<body>
<!-- 顶部导航按钮 -->
<div class="nav-buttons">
<!-- 返回上一页 -->
<button onclick="history.back()">返回上一页</button>
<!-- 返回主页 -->
<a href="{{ url_for('index') }}">返回主页</a>
</div>
<!-- 内容区 -->
<div class="content">
<!-- 左侧的计算器容器 -->
<div class="calculator-container boxed-container">
<div>
<h2 class="rendered">年龄计算器</h2>
<div class="calculator-container">
<label for="birthdate">输入你的出生日期:</label>
<input type="date" id="birthdate" class="styled-input">
<label for="specificDate">计算至某日期 (可选):</label>
<input type="date" id="specificDate" class="styled-input">
<button id="calculate-btn" class="calculator-btn">计算年龄</button>
<p id="result" class="formatted-result"></p>
</div>
</div>
</div>
<!-- 右侧的说明文字 -->
<div class="description">
<p>年龄计算器计算年龄时,给定出生日期,可以以年、月、天为单位显示结果。你还可以用它来计算两个日期之间的时间长度。</p>
<p>年龄计算器的结果包括:以年、月、天,月与天,周与天,以及总天数、总小时数、总分钟数和总秒数表示的年龄。</p>
<h3>如何计算年龄</h3>
<p>此年龄计算器使用两种类似但略有不同的方法来计算年龄。一种方法是以年、月、天为单位计算年龄,另一种则精确地以天数计算年龄。</p>
<p>在第一种方法中,计算器使用通用年、月的概念,不考虑平年和闰年的差异。例如,15岁的青少年不会说自己是12个平年加上3个闰年,因此计算器也采用这一通用假设。虽然我们知道年份可能有不同的长度,但在计算中将它们视为相等。</p>
<p>对于月份的计算也是如此。如果一个婴儿7个月大,父母不会说她是4个月31天、2个月30天和1个月28天,而是将所有月份视为相等。</p>
<p>在第二种方法中,计算器精确计算两个日期间总共过去的天数。这种计算会考虑到平年和闰年之间的差异,准确地计算日期间隔。</p>
<h3>总天数的计算</h3>
<h3>总天数的计算方式如下:</h3>
<ul>
<li>
平年天数 = 365 * 平年数
</li>
<li>
闰年天数 = 366 * 闰年数
</li>
<li>
剩余的部分年份天数
</li>
</ul>
<p>该计算器会识别在给定时间段内的闰年数量,并计算部分年份中的天数。例如,如果你出生于3月5日,今天是6月7日,计算器会精确地计算这两个日期之间的天数。</p>
<p>如果你想知道自己活了多少天,需要考虑闰年中的额外天数。你还需要了解哪些月份有31天,哪些月份有30天,以及有28天的月份。</p>
<he>各月份天数列表</he>
<ul>
<li>
1月 - 31天
</li>
<li>
2月 - 平年28天,闰年29天
</li>
<li>
3月 - 31天
</li>
<li>
4月 - 30天
</li>
<li>5月 - 31天</li>
<li>6月 - 30天</li>
<li>7月 - 31天</li>
<li>8月 - 31天</li>
<li>9月 - 30天</li>
<li>10月 - 31天</li>
<li>11月 - 30天</li>
<li>12月 - 31天</li>
</ul>
<h3>日期输入</h3>
<p>年龄计算器允许你输入一位数的日期,不需要添加前导零。你可以输入四位数的年份,也可以使用日期选择器。</p>
<p>这个计算器假设开始日期为第0天,并在第0天之后开始计数。例如,如果输入的日期是2022年3月15日到2022年3月18日,计算结果为3天。</p>
</div>
</div>
<script src="{{ url_for('static', filename='agecal/agecal.js') }}"></script>
</body>
</html>
没什么可以说明的,框加调整一至...
agecal.js 当前代码
<!DOCTYPE html>
<!--agecal.html-->
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>年龄计算器</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
<!-- 使用 Flask 的 url_for 函数来引用静态文件 -->
</head>
<body>
<!-- 顶部导航按钮 -->
<div class="nav-buttons">
<!-- 返回上一页 -->
<button onclick="history.back()">返回上一页</button>
<!-- 返回主页 -->
<a href="{{ url_for('index') }}">返回主页</a>
</div>
<!-- 内容区 -->
<div class="content">
<!-- 左侧的计算器容器 -->
<div class="calculator-container boxed-container">
<div>
<h2 class="rendered">年龄计算器</h2>
<div class="calculator-container">
<label for="birthdate">输入你的出生日期:</label>
<input type="date" id="birthdate" class="styled-input">
<label for="specificDate">计算至某日期 (可选):</label>
<input type="date" id="specificDate" class="styled-input">
<button id="calculate-btn" class="calculator-btn">计算年龄</button>
<p id="result" class="formatted-result"></p>
</div>
</div>
</div>
<!-- 右侧的说明文字 -->
<div class="description">
<p>年龄计算器计算年龄时,给定出生日期,可以以年、月、天为单位显示结果。你还可以用它来计算两个日期之间的时间长度。</p>
<p>年龄计算器的结果包括:以年、月、天,月与天,周与天,以及总天数、总小时数、总分钟数和总秒数表示的年龄。</p>
<h3>如何计算年龄</h3>
<p>此年龄计算器使用两种类似但略有不同的方法来计算年龄。一种方法是以年、月、天为单位计算年龄,另一种则精确地以天数计算年龄。</p>
<p>在第一种方法中,计算器使用通用年、月的概念,不考虑平年和闰年的差异。例如,15岁的青少年不会说自己是12个平年加上3个闰年,因此计算器也采用这一通用假设。虽然我们知道年份可能有不同的长度,但在计算中将它们视为相等。</p>
<p>对于月份的计算也是如此。如果一个婴儿7个月大,父母不会说她是4个月31天、2个月30天和1个月28天,而是将所有月份视为相等。</p>
<p>在第二种方法中,计算器精确计算两个日期间总共过去的天数。这种计算会考虑到平年和闰年之间的差异,准确地计算日期间隔。</p>
<h3>总天数的计算</h3>
<h3>总天数的计算方式如下:</h3>
<ul>
<li>
平年天数 = 365 * 平年数
</li>
<li>
闰年天数 = 366 * 闰年数
</li>
<li>
剩余的部分年份天数
</li>
</ul>
<p>该计算器会识别在给定时间段内的闰年数量,并计算部分年份中的天数。例如,如果你出生于3月5日,今天是6月7日,计算器会精确地计算这两个日期之间的天数。</p>
<p>如果你想知道自己活了多少天,需要考虑闰年中的额外天数。你还需要了解哪些月份有31天,哪些月份有30天,以及有28天的月份。</p>
<he>各月份天数列表</he>
<ul>
<li>
1月 - 31天
</li>
<li>
2月 - 平年28天,闰年29天
</li>
<li>
3月 - 31天
</li>
<li>
4月 - 30天
</li>
<li>5月 - 31天</li>
<li>6月 - 30天</li>
<li>7月 - 31天</li>
<li>8月 - 31天</li>
<li>9月 - 30天</li>
<li>10月 - 31天</li>
<li>11月 - 30天</li>
<li>12月 - 31天</li>
</ul>
<h3>日期输入</h3>
<p>年龄计算器允许你输入一位数的日期,不需要添加前导零。你可以输入四位数的年份,也可以使用日期选择器。</p>
<p>这个计算器假设开始日期为第0天,并在第0天之后开始计数。例如,如果输入的日期是2022年3月15日到2022年3月18日,计算结果为3天。</p>
</div>
</div>
<script src="{{ url_for('static', filename='agecal/agecal.js') }}"></script>
</body>
</html>
说明:
获取 HTML 元素 const
- birthdateInput:获取用户输入的出生日期。
- specificDateInput:可选输入,用于指定计算的目标日期(如果没有,默认使用当前日期)。
- resultElement:结果显示区域,用于展示计算后的年龄信息。
- calculateButton:按钮元素,当点击此按钮时,触发计算年龄的逻辑。
计算年龄函数 function calculateAge()
提醒:时区处理:通过将日期字符串后加上 'T00:00:00',强制将时间设定为本地时间的凌晨,避免浏览器默认解析为 UTC 时间的问题。
计算年龄和时间单位
const ageInYears = endDate.getFullYear() - birthDate.getFullYear();
const ageInMonths = (ageInYears * 12) + (endDate.getMonth() - birthDate.getMonth());
const ageInDays = Math.floor((endDate - birthDate) / (1000 * 60 * 60 * 24));
const ageInWeeks = Math.floor(ageInDays / 7);
const ageInHours = ageInDays * 24;
const ageInMinutes = ageInHours * 60;
const ageInSeconds = ageInMinutes * 60;
精确的年、月、天的计算
-
exactYears
、exactMonths
、exactDays
:通过精确计算月份和日期差值,确定剩余的月和天数。 - 日期修正:当天数为负数时,表示当前月份还没到,月份减少 1,天数增加到前一个月的天数;类似地,当月份为负数时,年数减少 1,月份数增加 12。
下一个生日的计算
-
nextBirthday
:通过目标年份、出生月份和日期计算下一次生日的日期。 - 修正生日年份:如果目标日期已经过了生日,下一次生日的年份加 1。
-
daysTillNextBirthday
:计算距离下一个生日的天数。
结果展示
- 以 HTML 的形式插入页面。显示的信息包括:
- 精确的年龄(年、月、天)。
- 以月、周、天为单位展示的详细年龄。
- 以小时、分钟和秒为单位的精确时间。
- 下一个生日的日期和剩余天数。
按钮点击事件监听器
当点击按钮时,触发 calculateAge() 函数,执行年龄的计算和结果的展示。
总结
- 支持年、月、天的详细计算。
- 以多种时间单位展示年龄,包括年、月、天、小时、分钟和秒。
- 解决时区问题,确保日期解析为本地时间。
- 计算距离下一个生日的时间,为用户提供有用的提醒。
workhours.html 当前代码
好像定义新的CSS,解决 "结果" tr td 排版问题
<!DOCTYPE html>
<!--workhours.html-->
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>工作时长计算器</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div>
<!-- 顶部导航按钮 -->
<div class="nav-buttons">
<!-- 返回上一页 -->
<button onclick="history.back()">返回上一页</button>
<!-- 返回主页 -->
<a href="{{ url_for('index') }}">返回主页</a>
</div>
<!-- 内容区 -->
<div class="content">
<!-- 左侧的计算器容器 -->
<div class="calculator-container boxed-container">
<div>
<h2 class="rendered"> 工作时长计算器</h2>
</div>
<div>
<div class="alignCenter note small" style="margin-bottom: 10px;">
输入不带冒号的时间:815, 1225 等
</div>
<div class="clock-container">
<!-- 12 小时时钟 -->
<div class="clock clock">
<input name="clock" type="radio" id="clock_0" value="12" onchange="toggleAmPm();" checked="">
<label for="clock_0">12 hour clock</label>
</div>
<!-- 24 小时时钟 -->
<div class="cell clock">
<input name="clock" type="radio" id="clock_1" value="24" onchange="toggleAmPm();">
<label for="clock_1">24 hour clock</label>
</div>
</div>
<!-- AM/PM 选择框 -->
<div class="clock-container">
<div class="cell">
<label for="startTime">开始时间:</label>
<input type="text" id="startTime" placeholder="hhmm" required maxlength="4" pattern="^([12]?[0-9][0-6][0-9])?$" inputmode="numeric" title="请输入有效的时间格式!">
<!-- AM/PM 选择框 -->
<div id="startAmPmContainer">
<select id="startAmPm">
<option value="AM" selected>AM</option>
<option value="PM">PM</option>
</select>
</div>
</div>
</div>
<div class="clock-container">
<div class="cell">
<label for="endTime">结束时间:</label>
<input type="text" id="endTime" placeholder="hhmm" required maxlength="4" pattern="^([12]?[0-9][0-6][0-9])?$" inputmode="numeric" title="请输入有效的时间格式!">
<!-- AM/PM 选择框 -->
<div id="endAmPmContainer">
<select id="endAmPm">
<option value="AM">AM</option>
<option value="PM" selected>PM</option>
</select>
</div>
</div>
</div>
<div class="clock-container">
<div class="row">
<div class="cell alignLeft">
<label for="break_minutes">休息时间:</label>
<input type="text" id="break_minutes" placeholder="0" inputmode="numeric" value="0" size="4" maxlength="3" onfocus="this.select()"> 分钟
</div>
</div>
</div>
</div>
<div class="button-group">
<div class="floatLeft">
<button class="clear-btn" onclick="clearFields()">清除</button>
</div>
<div class="floatRight">
<button id="calculateHours" class="calculator-btn">工时计算</button>
</div>
</div>
<div>
<p></p>
<div class="celleft">
<h3 style="display: inline;">结果: </h3>
<span id="answer"></span>
</div>
<!-- 使用标准的表格结构替换 div 模拟的表格 -->
<table class="prettytable">
<tr>
<th>时间合计(hh:mm)</th>
<td id="totalTime">00:00</td>
</tr>
<tr>
<th>十进制显示</th>
<td id="decimalHours">0.00 hours</td>
</tr>
<tr>
<th>分钟统计</th>
<td id="totalMinutes">0 minutes</td>
</tr>
</table>
</div>
</div>
<!-- 右侧的说明文字 -->
<div class="description">
<h3>使用这个计算器来累加时间表或工时卡的工时。</h3>
<p>只输入整数,如 1215 代表 12:15,或 137 代表 1:37。对于完整的工时卡,请使用工时卡计算器。</p>
<p>输入开始时间和结束时间时,不要使用 "." 或 ":"。</p>
<p>如果输入的数字为 1 到 12 之间的单个整数,系统将假定时间为 1:00 到 12:00。</p>
<p>系统假定“12 pm”为中午,“12 am”为午夜。</p>
<h3>将数字时间转换为十进制小时</h3>
<p>假设您计算的总时间为 7:15(7 小时 15 分钟),其等效的十进制时间为 7.25 小时。您需要使用十进制小时来计算工资。</p>
<h3>将分钟转换为十进制小时</h3>
<p>7:15 表示 7.0 小时外加 15 分钟。您需要将分钟部分转换为小时。</p>
<p>15 分钟乘以 1 小时除以 60 分钟,以小时为单位:</p>
<p>15 分 × (1 小时 / 60 分钟) = (15/60) 小时 = 0.25 小时</p>
<p>将 0.25 加到 7.0,我们的总时间就是 7.0 + 0.25 = 7.25 小时。</p>
<h3>反向操作:将十进制小时转换为分钟</h3>
<p>0.25 小时乘以每小时 60 分钟:</p>
<p>0.25 小时 × (60 分钟 / 1 小时) = (0.25 × 60) 分钟 = 15 分钟。</p>
</div>
<script src="{{ url_for('static', filename='workhours/workhourscal.js') }}"></script>
</div>
</body>
</html>
workhourscal.js 当前代码
// workhourscal.js
document.addEventListener('DOMContentLoaded', function() { //必须在 function 之前
// 绑定计算按钮的事件监听器
document.getElementById('calculateHours').addEventListener('click', calculateHours);
// 绑定清除按钮的事件监听器
// document.getElementById('clearFields').addEventListener('click', clearFields);
});
function toggleAmPm() {
// 获取选择的时钟模式
var is24HourClock = document.getElementById('clock_1').checked;
// 获取 AM/PM 选择框容器
var startAmPmContainer = document.getElementById('startAmPmContainer');
var endAmPmContainer = document.getElementById('endAmPmContainer');
// 如果选择了24小时制,隐藏AM/PM选择框;否则显示
if (is24HourClock) {
startAmPmContainer.style.display = 'none';
endAmPmContainer.style.display = 'none';
} else {
startAmPmContainer.style.display = 'block';
endAmPmContainer.style.display = 'block';
}
}
function calculateHours() {
const startTime = document.getElementById('startTime').value;
const endTime = document.getElementById('endTime').value;
const is24HourClock = document.getElementById('clock_1').checked; // 检查是否是24小时制
let startAmPm = '';
let endAmPm = '';
if (!is24HourClock) {
startAmPm = document.getElementById('startAmPm').value;
endAmPm = document.getElementById('endAmPm').value;
}
const breakMinutes = parseInt(document.getElementById('break_minutes').value) || 0;
// 重置提示和变量
document.getElementById('answer').textContent = ''; // 清空之前的提示
let midnightCrossed = false; // 初始化标记变量
let answerText = ''; // 初始化提示内容
// 验证输入的时间格式是否正确
if (!isValidTime(startTime) || !isValidTime(endTime)) {
document.getElementById('answer').textContent = '请输入有效的时间格式 (hhmm)';
return;
}
// 将时间转换为分钟(如果是24小时制,则忽略AM/PM)
const startMinutes = timeToMinutes(startTime, startAmPm, is24HourClock);
const endMinutes = timeToMinutes(endTime, endAmPm, is24HourClock);
let totalMinutes = endMinutes - startMinutes - breakMinutes;
// 处理跨越午夜的情况:如果结束时间早于开始时间,自动处理为跨越午夜的情况
if (totalMinutes < 0) {
totalMinutes += 1440; // 加上一天的分钟数
answerText = ' 注意:时间跨越了午夜!'; // 设置提醒文本
midnightCrossed = true; // 标记为跨越了午夜
}
// 计算小时和分钟
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
// 计算十进制小时
const decimalHours = (totalMinutes / 60).toFixed(2);
// 输出调试
console.log(`Hours: ${hours}, Minutes: ${minutes}, Decimal: ${decimalHours}, Total Minutes: ${totalMinutes}`);
// 将结果更新到表格的相应单元格中
document.getElementById('totalTime').textContent = `${hours}:${minutes.toString().padStart(2, '0')}`; // 总时间 (hh:mm)
document.getElementById('decimalHours').textContent = `${decimalHours} hours`; // 十进制小时
document.getElementById('totalMinutes').textContent = `${totalMinutes} minutes`; // 总分钟数
// 如果跨越了午夜,显示提示信息
if (midnightCrossed) {
document.getElementById('answer').textContent = answerText; // 显示跨越午夜的提醒
}
}
function timeToMinutes(time, amPm, is24HourClock) {
let hours = parseInt(time.slice(0, time.length - 2), 10);
let minutes = parseInt(time.slice(-2), 10);
// 如果是24小时制,忽略 AM/PM 处理
if (!is24HourClock) {
if (amPm === 'PM' && hours !== 12) {
hours += 12;
} else if (amPm === 'AM' && hours === 12) {
hours = 0;
}
}
return hours * 60 + minutes;
}
function isValidTime(time) {
return /^([01]?[0-9]|2[0-3])[0-5][0-9]$/.test(time); // 验证24小时制时间格式
}
function clearFields() {
document.getElementById('startTime').value = '';
document.getElementById('endTime').value = '';
document.getElementById('break_minutes').value = '0';
document.getElementById('answer').textContent = '';
document.getElementById('totalTime').textContent = `00:00`;
document.getElementById('decimalHours').textContent = `0.00 hours`;
document.getElementById('totalMinutes').textContent = `0 minutes`;
document.getElementById('answerText').textContent = ``;
//document.getElementById('midnightCrossed').textContent = ``;
}
time.html 当前代码
使用 style.css 替代了 script style
<!DOCTYPE html>
<!--time.html-->
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>时间单位转换器</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
<!-- 使用 Flask 的 url_for 函数来引用静态文件 -->
</head>
<body>
<!-- 顶部导航按钮 -->
<div class="nav-buttons">
<!-- 返回上一页 -->
<button onclick="history.back()">返回上一页</button>
<!-- 返回主页 -->
<a href="{{ url_for('index') }}">返回主页</a>
</div>
<!-- 内容区 -->
<div class="content">
<!-- 左侧的计算器容器 -->
<div class="calculator-container boxed-container">
<h2 class="rendered">时间单位转换器</h2>
<!-- 改为"从"并统一输入框风格 -->
<label for="input_value">从:</label>
<input type="number" id="input_value" class="styled-input" oninput="convertTime()" required>
<!-- 单位选择按钮 -->
<div class="unit-buttons">
<button type="button" class="unit-btn" onclick="selectUnit('nanoseconds')">纳秒</button>
<button type="button" class="unit-btn" onclick="selectUnit('microseconds')">微秒</button>
<button type="button" class="unit-btn" onclick="selectUnit('milliseconds')">毫秒</button>
<button type="button" class="unit-btn" onclick="selectUnit('seconds')">秒</button>
<button type="button" class="unit-btn" onclick="selectUnit('minutes')">分</button>
<button type="button" class="unit-btn" onclick="selectUnit('hours')">时</button>
<button type="button" class="unit-btn" onclick="selectUnit('days')">天</button>
<button type="button" class="unit-btn" onclick="selectUnit('weeks')">周</button>
<button type="button" class="unit-btn" onclick="selectUnit('months')">月</button>
<button type="button" class="unit-btn" onclick="selectUnit('years')">年</button>
</div>
<div class="button-container">
<button class="clear-btn" onclick="clearFields()">清除</button>
</div>
<div class="centered">
<div >
<h2>到:</h2>
</div>
<div class="normaltable">
<table>
<thead>
<tr>
<th>单位</th>
<th>换算值</th>
</tr>
</thead>
<tbody>
<tr>
<td>纳秒</td>
<td><span id="result_nanoseconds">0.00</span> 纳秒</td>
</tr>
<tr>
<td>微秒</td>
<td><span id="result_microseconds">0.00</span> 微秒</td>
</tr>
<tr>
<td>毫秒</td>
<td><span id="result_milliseconds">0.00</span> 毫秒</td>
</tr>
<tr>
<td>秒</td>
<td><span id="result_seconds">0.00</span> 秒</td>
</tr>
<tr>
<td>分钟</td>
<td><span id="result_minutes">0.00</span> 分钟</td>
</tr>
<tr>
<td>小时</td>
<td><span id="result_hours">0.00</span> 小时</td>
</tr>
<tr>
<td>天</td>
<td><span id="result_days">0.00</span> 天</td>
</tr>
<tr>
<td>周</td>
<td><span id="result_weeks">0.00</span> 周</td>
</tr>
<tr>
<td>月</td>
<td><span id="result_months">0.00</span> 月</td>
</tr>
<tr>
<td>年</td>
<td><span id="result_years">0.00</span> 年</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- 右侧的说明文字 -->
<div class="description">
<h2>单位换算说明</h2>
<p>输入您想要转换的时间值和单位,然后选择您要转换成的时间单位。您可以在秒 (seconds)、毫秒 (milliseconds)、微秒 (microseconds)、纳秒 (nanoseconds)、天 (days)、小时 (hours)、周 (weeks)、月 (months) 和年 (years) 之间进行转换。</p>
<p>在这个时间转换计算器中,月的计算使用平均每月30.416天。这个值等于每年365天除以每年12个月。365 ÷ 12 = 每月30.416天。</p>
<p>在这个时间转换器中,年的计算为每年365天。此计算器不考虑闰年中的额外一天(闰年每年有366天)。</p>
<h3>如何转换时间单位</h3>
<p>您可以使用转换因数通过乘法或除法将一个时间单位转换为另一个时间单位。通过了解转换因数,转换单位可以变成一个简单的数学问题:</p>
<p><strong>S * C = E</strong></p>
<p>其中 <strong>S</strong> 为起始值,<strong>C</strong>为转换因子,<strong>E</strong>为转换结果</p>
<h4>秒的转换</h4>
<p>下表包含将任何时间值转换为秒的转换因数,使用乘法即可完成转换。</p>
<p><strong>示例:</strong> 将120分钟转换为秒</p>
<p>将120分钟乘以每分钟60秒:120 分钟 * 60 秒/分钟 = 7200 秒</p>
<p><strong>示例:</strong> 将28,800秒转换为小时</p>
<p>将28,800秒乘以每秒1/3600小时:这与将28,800秒除以每小时3600秒相同:</p>
<p>28,800 秒 ÷ 3600 秒/小时 = 8 小时</p>
<p>要在左列中的任何单位之间进行转换,例如从 A 转换为 B,您可以乘以 A 的系数以将 A 转换为秒,然后除以 B 的系数以转换出秒。或者,您可以通过将 A 的转换系数除以 B 的转换系数来找到简化的系数。</p>
<p>要将分钟转换为小时,请将分钟数乘以 60,然后除以 3600。简化后,这相当于乘以 60/3600,即 0.016666667。要直接从分钟转换为小时,请乘以 0.016。</p>
</div>
</div>
<!-- 单位、符号和转换值表格 -->
<h2 class="table-section-title">单位、符号和转换值</h2>
<table class="conversion-table">
<thead>
<tr>
<th>单位</th>
<th>符号</th>
<th>转换为秒的乘数</th>
</tr>
</thead>
<tbody>
<tr><td>纳秒</td><td>ns</td><td>0.000000001 秒的十亿分之一</td></tr>
<tr><td>微秒</td><td>ms</td><td>0.000001 秒的百万分之一</td></tr>
<tr><td>毫秒</td><td>ms</td><td>0.001 秒的千分之一</td></tr>
<tr><td>秒</td><td>s</td><td>1</td></tr>
<tr><td>秒(恒星)</td><td>s</td><td>0.99726956</td></tr>
<tr><td>分钟</td><td>min</td><td>60</td></tr>
<tr><td>分钟(恒星)</td><td>min</td><td>59.83617361</td></tr>
<tr><td>小时</td><td>h</td><td>3600</td></tr>
<tr><td>小时(恒星)</td><td>h</td><td>3590.170417</td></tr>
<tr><td>天</td><td>d</td><td>86400</td></tr>
<tr><td>天(恒星)</td><td>d</td><td>86164.09</td></tr>
<tr><td>周</td><td>wk</td><td>604800</td></tr>
<tr><td>月</td><td>mo</td><td>2628000</td></tr>
<tr><td>shake</td><td>shake</td><td>0.00000001</td></tr>
<tr><td>年</td><td>yr</td><td>31536000</td></tr>
<tr><td>年(恒星)</td><td>yr</td><td>31449892.85</td></tr>
<tr><td>十年</td><td>dec</td><td>315360000</td></tr>
<tr><td>世纪</td><td>c</td><td>3153600000</td></tr>
<tr><td>千年</td><td></td><td>31536000000</td></tr>
</tbody>
</table>
<div class="sidereal">
<h3>恒星日 (Sidereal Day)</h3>
<p>恒星日:天文学中使用的时间单位,相当于地球相对于恒星完成一次旋转的时间。如果我们可以从太阳系外观察地球,我们会看到它在一年内实际完成了 366.242 次旋转(即绕太阳一圈)。我们只计算 365.242 次旋转,因为我们绕太阳公转时其中一次旋转被抵消。因此,恒星日比平均太阳日短 1/366.242。恒星日等于 23 小时 56 分 4.090 54 秒,或 86164.090 54 秒。</p>
<p><strong>为什么恒星日比太阳日短?</strong><br>
这是因为地球不仅在自转,还围绕太阳公转。当地球自转一圈时,它也在围绕太阳前进了一小段路,因此地球需要再多旋转一点,太阳才会回到天空中原来的位置。这就是为什么太阳日比恒星日长大约4分钟的原因。</p>
<p><strong>应用:</strong><br>
恒星日的概念在天文学中有着重要的应用,特别是在精确测量天体的位置和运动时。因为恒星日更加接近地球自转的真实周期,天文观测使用恒星日来追踪天体的变化。</p>
<p>总的来说,恒星日是相对于远处恒星的一天,时间大约是23小时56分钟,稍短于我们常用的太阳日。</p>
</div>
<div class="references">
<p>资料来源:<a href="http://www.ibiblio.org/units/" target="_blank">How Many? A Dictionary of Units of Measurement</a> 访问日期:2023-07-25。</p>
<h3>参考资料/进一步阅读</h3>
<p>The National Institute of Standards and Technology (NIST) -
<a href="https://www.nist.gov/physical-measurement-laboratory/special-publication-811" target="_blank" rel="noopener">
<em>The NIST Guide for the Use of the International System of Units</em>
</a> - Appendix B, subsections
<a href="https://www.nist.gov/physical-measurement-laboratory/nist-guide-si-appendix-b8" target="_blank" rel="noopener">
B.8 Factors for Units Listed Alphabetically
</a> and
<a href="https://www.nist.gov/pml/nist-guide-si-appendix-b9-factors-units-listed-kind-quantity-or-field-science" target="_blank" rel="noopener">
B.9 Factors for units listed by kind of quantity or field of science
</a>.
</p>
<p>Lide, David R., Daniel (Editor-in-Chief).
<em><a href="https://books.google.com/books/about/CRC_Handbook_of_Chemistry_and_Physics_89.html?id=KACWPwAACAAJ" target="_blank" rel="noopener">
CRC Handbook of Chemistry and Physics, 89th Edition</a></em>, New York, NY: CRC Press, p. 1-28, 2008.
</p>
<p>Wikipedia contributors. "Conversion of units" Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, last visited 26 Jun. 2011.
<a href="https://en.wikipedia.org/wiki/Conversion_of_units" target="_blank" rel="noopener">Read more on Wikipedia</a>.
</p>
</div>
<script src="{{ url_for('static', filename='time/timercal.js') }}"></script>
</body>
</html>
timecal.js 当前代码
// JavaScript文件:timercal.js
// 初始默认选中的单位是'秒'
let selectedUnit = 'seconds';
// 根据输入值和选定的单位转换时间
function convertTime() {
const inputValue = parseFloat(document.getElementById('input_value').value) || 0;
let totalSeconds = 0;
// 根据选定的单位将输入值转换为总秒数
switch (selectedUnit) {
case 'nanoseconds':
totalSeconds = inputValue / 1000000000;
break;
case 'microseconds':
totalSeconds = inputValue / 1000000;
break;
case 'milliseconds':
totalSeconds = inputValue / 1000;
break;
case 'seconds':
totalSeconds = inputValue;
break;
case 'minutes':
totalSeconds = inputValue * 60;
break;
case 'hours':
totalSeconds = inputValue * 3600;
break;
case 'days':
totalSeconds = inputValue * 86400;
break
case 'weeks':
totalSeconds = inputValue * 604800;
break;
case 'months':
totalSeconds = inputValue * 86400 * 30.44; // 使用月平均天数来近似
break;
case 'years':
totalSeconds = inputValue * 86400 * 365.25; // 考虑闰年的平均秒数
break;
}
// 从总秒数计算所有单位的结果
const results = calculateTimeComponents(totalSeconds);
updateUI(results);
}
// 从秒数计算时间各组成部分
function calculateTimeComponents(seconds) {
return {
nanoseconds: seconds * 1000000000,
microseconds: seconds * 1000000,
milliseconds: seconds * 1000,
seconds: seconds,
minutes: seconds / 60,
hours: seconds / 3600,
days: seconds / 86400,
weeks: seconds / (86400 * 7),
months: seconds / (86400 * 30.44),
years: seconds / (86400 * 365.25)
};
}
function updateUI(results) {
document.getElementById('result_nanoseconds').textContent = results.nanoseconds.toFixed(2) ;
document.getElementById('result_microseconds').textContent = results.microseconds.toFixed(2) ;
document.getElementById('result_milliseconds').textContent = results.milliseconds.toFixed(2) ;
document.getElementById('result_seconds').textContent = results.seconds.toFixed(2) ;
document.getElementById('result_minutes').textContent = results.minutes.toFixed(2) ;
document.getElementById('result_hours').textContent = results.hours.toFixed(2);
document.getElementById('result_days').textContent = results.days.toFixed(2);
document.getElementById('result_weeks').textContent = results.weeks.toFixed(2);
document.getElementById('result_months').textContent = results.months.toFixed(2);
document.getElementById('result_years').textContent = results.years.toFixed(2);
}
// 设置选定的单位并突出显示活动按钮
function selectUnit(unit) {
selectedUnit = unit;
const buttons = document.querySelectorAll('.unit-btn');
buttons.forEach(btn => {
btn.classList.remove('active');
if (btn.textContent.toLowerCase().includes(unit)) {
btn.classList.add('active');
}
});
convertTime(); // 使用新单位重新计算
}
// 清除所有字段并重置输出
function clearFields() {
document.getElementById('input_value').value = '';
convertTime(); // 重新计算以显示零值
}
Style.css 当前代码
/* Root CSS variables for easy theme management */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f4f4f4;
}
.tools-list {
list-style: none;
padding: 0;
margin: 0;
display: block;
width: 100%;
}
.tools-list a {
display: inline-block;
width: 100%; /* 让按钮宽度填满父容器 */
max-width: 180px; /* 设置最大宽度,避免按钮过大 */
padding: 10px 15px;
font-size: 1.2em;
color: #007BFF;
border: 1px solid #007BFF;
border-radius: 5px;
text-align: center; /* 水平居中 */
text-decoration: none;
transition: background-color 0.3s, color 0.3s;
background-color: white; /* 按钮背景色 */
margin-left: auto;
margin-right: auto;
}
.tools-list a:hover {
background-color: #007BFF;
color: white;
}
.tools-list li {
margin-bottom: 20px; /* 增加底部外边距 */
}
/* 右上角导航按钮 */
.nav-buttons {
position: absolute;
top: 20px;
right: 20px;
}
.nav-buttons a, .nav-buttons button {
text-decoration: none;
font-size: 0.9em;
color: white;
background-color: #007BFF;
border: none;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
margin-left: 10px;
}
.nav-buttons a:hover, .nav-buttons button:hover {
background-color: #0056b3;
}
.nav-buttons button {
font-size: 0.9em;
}
h1, h2 {
text-align: center;
color: #333;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 20px;
}
.calculator-container {
flex: 1;
min-width: 300px;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-top: 40px;
align-items: center;
}
.description {
flex: 2;
min-width: 500px;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-top: 40px;
}
table {
width: 33%;
margin: 0 auto;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ddd;
}
th, td {
text-align: center;
padding: 8px;
font-size: 1.1rem;
}
th {
background-color: #f0f0f0;
}
.sidereal {
margin-top: 40px;
font-size: 0.9rem;
line-height: 1.6;
}
.references {
margin-top: 20px;
font-size: 0.85rem;
}
.references a {
color: blue;
text-decoration: none;
}
.boxed-container {
border: 1px solid #87CEEB;
padding: 10px;
background-color: #f0f8ff;
border-radius: 10px;
box-shadow: 3px 3px 15px rgba(135, 206, 235, 0.5);
margin-bottom: 20px;
align-items: center;
}
.styled-input {
padding: 10px;
width: 100%;
margin-top: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1.1em;
box-sizing: border-box;
}
.unit-buttons {
margin: 10px 0;
}
.unit-btn {
padding: 10px 20px;
margin: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.unit-btn.active {
background-color: #87CEEB;
border-color: #007BFF;
color: white;
}
.unit-btn:hover {
background-color: #ddd;
}
.clear-btn {
/*margin-top: 20px;
margin-bottom: 10px;*/
padding: 15px 30px;
font-size: 1.2em;
background-color: #ff4c4c;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
justify-content:space-between ;
}
.clear-btn:hover {
background-color: #ff3333;
}
.calculator-btn {
/*margin-top: 20px;
margin-bottom: 10px;*/
padding: 15px 30px;
font-size: 1.2em;
background-color: #0056b3;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
justify-content:space-between ;
}
.calculator-btn:hover {
background-color:#0056b3;
}
th, td {
white-space: nowrap;
}
.table-section-title {
font-size: 1.5em;
font-weight: bold;
color: #333;
margin-top: 40px;
text-align: center;
}
.conversion-table {
width: 33%;
margin: 0 auto;
border-collapse: collapse;
margin-top: 20px;
margin-bottom: 40px;
}
.conversion-table th, .conversion-table td {
border: 1px solid #ddd;
padding: 12px;
text-align: center;
}
.conversion-table th {
background-color: #f0f8ff;
font-weight: bold;
font-size: 1.2em;
}
.conversion-table td {
font-size: 1em;
}
.conversion-table tr:nth-child(even) {
background-color: #f9f9f9;
}
.conversion-table tr:nth-child(odd) {
background-color: #ffffff;
}
h1 {
text-align: left;
color: #333;
font-size: 2em;
margin: 10px 0;
}
h2.rendered {
background: linear-gradient(90deg, #87CEEB, #4b79a1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 2em;
font-weight: bold;
text-align: center;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
margin: 10px 0;
padding: 10px;
display: inline-block;
width: 100%;
}
label, .styled-input {
margin-top: 10px;
margin-bottom: 10px;
}
label[for="input_value"] {
font-size: 1.5em;
font-weight: bold;
color: #000000;
display: block;
margin-bottom: 10px;
}
.formatted-result {
text-align: center; /* 水平居中 */
font-size: 1.5em; /* 适当调整字体大小 */
font-weight: normal; /* 粗体显示 */
margin: 10px 0; /* 上下增加一些间距 */
}
.button-container {
display: flex;
}
.alignCenter{
text-align: center;
}
.clock-container {
display: flex;
align-items: center; /* 水平居中 */
justify-content: center; /* 垂直居中 */
gap: 20px; /* 设置两个按钮之间的间距 */
margin-bottom: 10px; /* 各个元素之间添加空行 */
}
.button-group {
display: flex;
justify-content: space-between; /* 左右对齐 */
margin-top: 20px; /* 为按钮与上面内容添加空行 */
}
button {
padding: 10px 20px; /* 调整按钮的内边距,减小按钮大小 */
font-size: 1rem; /* 控制按钮内文字的大小 */
}
#result {
text-align: center;
flex: 2; /* 确保结果区域在两个按钮之间有足够的空间 */
}
.floatLeft, .floatRight {
display: inline-block; /* 保持按钮的内联块布局 */
margin-top: 10px; /* 控制每个按钮与其他元素之间的间距 */
}
.note {
font-weight: 400;
color: #666 !important; /* 强制灰色 */
}
.small {
font-size: 1rem !important; /* 强制较小的字体 */
}
input[type="text"]{
width: 80px; /* 设置输入框的宽度为 80px,调整为你需要的尺寸 */
padding: 5px; /* 控制输入框内边距 */
font-size: 1em; /* 控制文字大小 */
box-sizing: border-box; /* 确保 padding 不会影响宽度 */
}
select{
width: 52px; /* 将 select 框宽度调整为 60px */
padding: 5px;
font-size: 0.8em;
box-sizing: border-box;
}
table{
margin:0;
}
/*.centered{
width:auto;
margin-left:auto;
margin-right:auto;
}*/
.centered {
display: flex;
width: 100%;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中,如果需要 */
flex-direction: column; /* 垂直排列内容 */
text-align: center; /* 确保文本也居中 */
margin-left: auto;
margin-right: auto;
}
.centered h2 {
margin-bottom: 10px; /* 减少 h2 标题的底部外边距 */
}
.prettytable {
width: 100%;
border-collapse: collapse;
background-color: #fcfcfc;
margin: 1em 0;
border: 1px solid #aaa;
table-layout: fixed
}
.prettytable th, .prettytable td {
padding: 10px;
border: 1px solid #aaa;
text-align: center;
}
.prettytable th {
background-color: #eee;
font-weight: 700;
}
.normaltable {
background-color: #fcfcfc;
margin: 1em 0;
border: 1px solid #aaa;
margin-top: 0; /* 取消表格容器的顶部外边距 */
}
.normaltable th, .normaltable td {
padding: 10px;
border: 1px solid #aaa;
text-align: center;
}
.normaltable th {
background-color: #eee;
font-weight: 700;
}
.normaltable table {
width: 100%;
table-layout: fixed;
margin-top: 0; /* 确保表格的顶部外边距为 0 */
padding-top: 0; /* 确保没有额外的内边距 */
}
.cell {
display: flex;
align-items: center; /* 确保内容垂直居中 */
}
#startAmPmContainer, #endAmPmContainer {
margin-left: 10px; /* 给 AM/PM 选择框留出适当的左边距 */
}
.celleft {
margin-right: 10px; /* 留出一些右边距 */
}
说明
一直在更新。后来越改越多...
Docker 部署
Dockerfile 代码
# 使用官方的 Python 3.12.3 slim 版本作为基础镜像
FROM python:3.12.3-slim
# Set the working directory in the container
WORKDIR /app/calculator
# Copy the current directory contents into the container at /app/calculator
COPY . /app/calculator
# 升级 pip
RUN pip install --upgrade pip
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Make port 9007 available to the world outside this container
EXPOSE 9007
# 设置环境变量以指定Flask运行的主机和端口
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_RUN_PORT=9007
# Run app.py when the container launches
CMD ["python", "./app.py"]
requirements.txt 内容
Flask
布署命令 端口9007
创建 Image
[/share/Multimedia/2024-MyProgramFiles/11.Calculator] # docker build -t calculator .
创建 Container
[/share/Multimedia/2024-MyProgramFiles/11.Calculator] # docker run -d -p 9007:9007 --name calculator_container calculator
e964f300bec0be65307bfb3ddfb09f80a76aac1675461e88cfa76a404edd2601
[/share/Multimedia/2024-MyProgramFiles/11.Calculator] #
启动容器 container
docker start calculator_container
查看容器日志
[/share/Multimedia/2024-MyProgramFiles/11.Calculator] # docker logs calculator_container
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:9007
* Running on http://10.0.3.8:9007
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 100-809-782
[/share/Multimedia/2024-MyProgramFiles/11.Calculator] #
让容器一直运行
方法1:
#docker update --restart always calculator_container
方法2:
docker run -d -p 9007:9007 --name calculator_container --restart always calculator
总结
放到NAS上最方便~
加入到 bookmark
以上所有的 项目 完整 “代码” 在我写的文章中可以找到,都有 dockerfile requirements.txt 方便 docker 部署。