ACM-時區間時間的轉換

問題描述

        直到 19 世紀,時間校準是一個純粹的地方現象。每一個村莊當太陽升到最高點的時候把他們的時鐘調到中午 12 點。一個鐘錶製造商人家或者村裏主表的時間被認爲是官方時間,市民們把自家的鐘表和這個時間對齊。每週一些熱心的市民會帶着時間標準的表,遊走大街小巷爲其他市民對錶。在城市之間旅遊的話,在到達新地方的時候需要把懷錶校準。但是,當鐵路投入使用之後,越來越多的人頻繁地長距離地往來,時間變得越來越重要。在鐵路的早期,時刻表非常讓人迷惑,每一個所謂的停靠時間都是基於停靠地點的當地時間。時間的標準化對於鐵路的高效運營變得非常重要。
        在 1878 年,加拿大人 Sir Sanford Fleming 提議使用一個全球的時區(這個建議被採納,並衍生了今天我們所使用的全球時區的概念),他建議把世界分成 24 個時區,每一個跨越 15 度經線(因爲地球的經度 360 度,劃分成 24 塊後,一塊爲 15 度)。Sir SanfordFleming 的方法解決了一個全球性的時間混亂的問題。
        美國鐵路公司於 1883 年 11 月 18 日使用了 Fleming 提議的時間方式。 1884 年一個國際子午線會議在華盛頓召開,他的目的是選擇一個合適的本初子午線。大會最終選定了格林威治爲標準的 0 度。儘管時區被確定了下來,但是各個國家並沒有立刻更改他們的時間規範,在美國,儘管到 1895 年已經有很多州開始使用標準時區時間,國會直到1918 年才強制使用會議制定的時間規範。
        今天各個國家使用的是一個 Fleming 時區規範的一個變種,中國一共跨越了 5 個時區,但是使用了一個統一的時間規範,比 Coordinated Universal Time( UTC,格林威制時間)早 8 個小時。俄羅斯也擁護這個時區規範,儘管整個國家使用的時間和標準時區提前了 1 個小時。
        澳大利亞使用 3 個時區,其中主時區提前於他按 Fleming 規範的時區半小時。很多中東國家也使用了半時時區(即不是按照 Fleming 的 24 個整數時區)。
        因爲時區是對經度進行劃分,在南極或者北極工作的科學家直接使用了 UTC 時間,否則南極大陸將被分解成 24 個時區。
        時區的轉化表如下:

UTC Coordinated Universal Time
GMT Greenwich Mean Time, 定義爲 UTC
BST British Summer Time, 定義爲 UTC+1 hour
IST Irish Summer Time, 定義爲 UTC+1 hour
WET Western Europe Time, 定義爲 UTC
WEST Western Europe Summer Time, 定義爲 UTC+1 hour
CET Central Europe Time, 定義爲 UTC+1
CEST Central Europe Summer Time, 定義爲 UTC+2
EET Eastern Europe Time, 定義爲 UTC+2
EEST Eastern Europe Summer Time, 定義爲 UTC+3
MSK Moscow Time, 定義爲 UTC+3
MSD Moscow Summer Time, 定義爲 UTC+4
AST Atlantic Standard Time, 定義爲 UTC-4 hours
ADT Atlantic Daylight Time, 定義爲 UTC-3 hours
NST Newfoundland Standard Time, 定義爲 UTC-3.5 hours
NDT Newfoundland Daylight Time, 定義爲 UTC-2.5 hours
EST Eastern Standard Time, 定義爲 UTC-5 hours
EDT Eastern Daylight Saving Time, 定義爲 UTC-4 hours
CST Central Standard Time, 定義爲 UTC-6 hours
CDT Central Daylight Saving Time, 定義爲 UTC-5 hours
MST Mountain Standard Time, 定義爲 UTC-7 hours
MDT Mountain Daylight Saving Time, 定義爲 UTC-6 hours
PST Pacific Standard Time, 定義爲 UTC-8 hours
PDT Pacific Daylight Saving Time, 定義爲 UTC-7 hours
HST Hawaiian Standard Time, 定義爲 UTC-10 hours
AKST Alaska Standard Time, 定義爲 UTC-9 hours
AKDT Alaska Standard Daylight Saving Time, 定義爲 UTC-8 hours
AEST Australian Eastern Standard Time, 定義爲 UTC+10 hours
AEDT Australian Eastern Daylight Time, 定義爲 UTC+11 hours
ACST Australian Central Standard Time, 定義爲 UTC+9.5 hours
ACDT Australian Central Daylight Time, 定義爲 UTC+10.5 hours
AWST Australian Western Standard Time, 定義爲 UTC+8 hours

下面給出了一些時間,請在不同時區之間進行轉化。

輸入數據

       輸入的第一行包含了一個整數 N,表示有 N 組測試數據。接下來 N 行,每一行包括一個時間和兩個時區的縮寫,它們之間用空格隔開。時間由標準的 a.m./p.m 給出。midnight 表示晚上 12 點( 12:00 a.m.), noon 表示中午 12 點( 12:00 p.m.)。

輸出要求

       假設輸入行給出的時間是在第一個時區中的標準時間,要求輸出這個時間在第二個時區中的標準時間。

輸入樣例

4
noon HST CEST
11:29 a.m. EST GMT
6:01 p.m. CST UTC
12:40 p.m. ADT MSK

輸出樣例

midnight
4:29 p.m.
12:01 a.m.
6:40 p.m.

解題思路

        這個題目要求在兩個時區之間進行時間的轉換。我們根據每個時區與格林威治時間的轉換公式可以推算出兩個時區之間的差別。問題的解決方法不難想到,只是日期處理類問題具有共同的特點就是輸入輸出比較麻煩,有一些需要特殊處理的情況,例如轉換後多出一天或少了一天的情況需要處理。具體到這個題目來說:輸入時,除了一般的時間表示法:時:分a.m/p.m.之外,要特殊處理 noon 和 midnight;在直接通過格林威治時間進行轉換後,要判斷是否超過一天或減少了一天的情況;在輸出時間時,要對 noon 和 midnight 進行特殊處理。
        解決這個問題時,關鍵的是確定兩個時區之間的時差。因爲時區是用字符串形式給出的,所以要先將時區對應到該時區與格林威治時間的時差上。有了每個時區與格林威治時間的時差,就可以計算任意兩個時區之間的時差。

參考程序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int difference(char* zone1,char* zone2){// 計算兩個時區之間的時差,以分鐘爲單位。
	char* zone[32]={"UTC","GMT","BST","IST","WET","WEST",
					"CET","CEST","EET","EEST","MSK",
					"MSD","AST","ADT","NST","NDT",
					"EST","EDT","CST","CDT","MST",
					"MDT","PST","PDT","HST","AKST",
					"AKDT","AEST","AEDT","ACST","ACDT",
					"AWST"};
	float time[32]={0,0,1,1,0,1,1,2,2,3,3,4,-4,-3,-3.5,-2.5,-5,-4,-6,-5,-7,
					-6,-8,-7,-10,-9,-8,10,11,9.5,10.5,8};
	int i,j;
	for(i=0;strcmp(zone[i],zone1);i++);//找到第一個時區對應的位置
	for(j=0;strcmp(zone[j],zone2);j++);//找到第二個時區對應的位置
	return (int)((time[i] - time[j])*60);//計算並返回時差,以分鐘爲單位
}
int main()
{
	int nCases;
	cin>>nCases;// 讀入測試數據數目
	for(int i=0;i<nCases;i++){// 對每組輸入數據
		char time[9];// 輸入的時間
		int hours=0,minutes=0;// 轉換成整數
		cin>>time; //讀入時間
		switch(time[0]){
			case 'n':// 輸入爲”noon”
					hours=12;
					break;
			case 'm':	// 輸入爲”midnight”
					break;
			default:
				sscanf(time,"%d:%d",&hours,&minutes);// 輸入爲 時:分
				hours %= 12;
				cin>>time;
				if(time[0] == 'p')
					hours += 12;
		}
		char timezone1[5],timezone2[5];
		cin>>timezone1>>timezone2;// 讀入時區
		int newTime;//以分鐘爲單位
		newTime = hours * 60 + minutes + difference(timezone2,timezone1);
		if(newTime < 0)
			newTime += 1440;// 提前一天,將負的時間加上一天。
		newTime %= 1440;// 如果超過一天,將一天的時間減去。
		switch(newTime){
			case 0:
				cout<<"midnight"<<endl;// 新時間爲凌晨
				break;
			case 720:
				cout<<"noon"<<endl;// 新時間爲中午
				break;
			default:
				hours = newTime / 60;
				minutes = newTime % 60;
				if(hours == 0){// 凌晨, 分鐘不爲 0
					printf("12:%02d a.m.\n",minutes);
				}else if(hours < 12){// 上午
					printf("%d:%02d p.m.\n",hours,minutes);
				}else if(hours == 12){// 中午, 分鐘不爲 0
					printf("12:%02d p.m.\n", minutes);
				}else{// 下午
					printf("%d:%02d p.m.\n", hours%12, minutes);
				}
		}
	}
	return 0;
}


發佈了80 篇原創文章 · 獲贊 34 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章